diff --git a/.gitignore b/.gitignore index 43fe390a0..3c761969d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ resources/3rdparty/log4cplus-1.1.3-rc1/ resources/3rdparty/gtest-1.7.0/ resources/3rdparty/eigen/ -resources/3rdparty/gmm-4.2/ +resources/3rdparty/gmm-5.2/ resources/3rdparty/cudd-3.0.0/ resources/3rdparty/xercesc-3.1.2/ #Visual Studio files diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e2e6c883..9fafa9849 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,11 @@ The releases of major and minor versions contain an overview of changes since th Version 1.1.x ------------- -Long run average computation via ValueIteration, LP based MDP model checking, parametric model checking has an own binary +- long run average computation via value iteration +- LP based MDP model checking +- parametric model checking has an own binary +- solvers can now expose requirements +- unbounded reachability and reachability rewards now correctly respect solver requirements ### Version 1.1.1 - c++ api changes: Building model takes BuilderOptions instead of extended list of Booleans, does not depend on settings anymore. diff --git a/CMakeLists.txt b/CMakeLists.txt index 32e5ff8b2..b6c56e03c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -386,9 +386,7 @@ string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.[0-9]+\\-[0-9]+\\-[a-z0-9]+\\-(.*)" "\\ # now check whether the git version lookup failed if (STORM_VERSION_MAJOR MATCHES "NOTFOUND") - set(STORM_VERSION_MAJOR 1) - set(STORM_VERSION_MINOR 0) - set(STORM_VERSION_PATCH 2) + include(version.cmake) set(STORM_VERSION_GIT_HASH "") set(STORM_VERSION_COMMITS_AHEAD 0) set(STORM_VERSION_DIRTY boost::none) diff --git a/resources/3rdparty/CMakeLists.txt b/resources/3rdparty/CMakeLists.txt index ce379dc0e..34e38bbf7 100644 --- a/resources/3rdparty/CMakeLists.txt +++ b/resources/3rdparty/CMakeLists.txt @@ -34,7 +34,7 @@ list(APPEND STORM_DEP_TARGETS l3pp) ## ############################################################# -add_imported_library_interface(gmm "${PROJECT_SOURCE_DIR}/resources/3rdparty/gmm-5.0/include") +add_imported_library_interface(gmm "${PROJECT_SOURCE_DIR}/resources/3rdparty/gmm-5.2/include") list(APPEND STORM_DEP_TARGETS gmm) ############################################################# diff --git a/resources/3rdparty/gmm-5.0/README b/resources/3rdparty/gmm-5.0/README deleted file mode 100755 index afeab4850..000000000 --- a/resources/3rdparty/gmm-5.0/README +++ /dev/null @@ -1 +0,0 @@ -Please read BUGS, INSTALL diff --git a/resources/3rdparty/gmm-5.0/m4/ax_check_cxx_flag.m4 b/resources/3rdparty/gmm-5.0/m4/ax_check_cxx_flag.m4 deleted file mode 100644 index e0f8d65ba..000000000 --- a/resources/3rdparty/gmm-5.0/m4/ax_check_cxx_flag.m4 +++ /dev/null @@ -1,17 +0,0 @@ -dnl based on http://www.gnu.org/software/ac-archive/htmldoc/ac_check_cc_opt.html -dnl from Guido Draheim -AC_DEFUN([AC_CHECK_CXX_FLAG], -[AC_MSG_CHECKING([whether ${CXX} accepts $1]) - -echo 'int main(){}' > conftest.c -if test -z "`${CXX} $1 -o conftest conftest.c 2>&1`"; then - $2="${$2} $1" - echo "yes" -else - echo "no" - $3 -fi -dnl echo "$2=${$2}" -rm -f conftest* -]) - diff --git a/resources/3rdparty/gmm-5.0/AUTHORS b/resources/3rdparty/gmm-5.2/AUTHORS similarity index 80% rename from resources/3rdparty/gmm-5.0/AUTHORS rename to resources/3rdparty/gmm-5.2/AUTHORS index 542ae2225..0bad54b4c 100644 --- a/resources/3rdparty/gmm-5.0/AUTHORS +++ b/resources/3rdparty/gmm-5.2/AUTHORS @@ -1,4 +1,4 @@ -Authors of GETFEM++ +Authors of GetFEM++ Yves RENARD. Initial project. All the project. diff --git a/resources/3rdparty/gmm-5.0/COPYING b/resources/3rdparty/gmm-5.2/COPYING similarity index 55% rename from resources/3rdparty/gmm-5.0/COPYING rename to resources/3rdparty/gmm-5.2/COPYING index 867d8310d..65bf0a958 100644 --- a/resources/3rdparty/gmm-5.0/COPYING +++ b/resources/3rdparty/gmm-5.2/COPYING @@ -1,12 +1,13 @@ -Getfem++ is free software; you can redistribute it and/or modify it +GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published -by the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version along with the GCC Runtime Library +by the Free Software Foundation; either version 3 of the License, or +(at your option) any later version along with the GCC Runtime Library Exception either version 3.1 or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GCC Runtime Library Exception for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software Foundation, -Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. \ No newline at end of file +along with this program (see GNU_GPL_V3, GNU_LGPL_V3 and +GNU_GCC_RUNTIME_EXCEPTION files); if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. \ No newline at end of file diff --git a/resources/3rdparty/gmm-5.0/ChangeLog b/resources/3rdparty/gmm-5.2/ChangeLog similarity index 100% rename from resources/3rdparty/gmm-5.0/ChangeLog rename to resources/3rdparty/gmm-5.2/ChangeLog diff --git a/resources/3rdparty/gmm-5.0/INSTALL b/resources/3rdparty/gmm-5.2/INSTALL similarity index 100% rename from resources/3rdparty/gmm-5.0/INSTALL rename to resources/3rdparty/gmm-5.2/INSTALL diff --git a/resources/3rdparty/gmm-5.0/Makefile.am b/resources/3rdparty/gmm-5.2/Makefile.am similarity index 100% rename from resources/3rdparty/gmm-5.0/Makefile.am rename to resources/3rdparty/gmm-5.2/Makefile.am diff --git a/resources/3rdparty/gmm-5.0/Makefile.in b/resources/3rdparty/gmm-5.2/Makefile.in similarity index 100% rename from resources/3rdparty/gmm-5.0/Makefile.in rename to resources/3rdparty/gmm-5.2/Makefile.in diff --git a/resources/3rdparty/gmm-5.0/NEWS b/resources/3rdparty/gmm-5.2/NEWS similarity index 100% rename from resources/3rdparty/gmm-5.0/NEWS rename to resources/3rdparty/gmm-5.2/NEWS diff --git a/resources/3rdparty/gmm-5.2/README b/resources/3rdparty/gmm-5.2/README new file mode 100644 index 000000000..1819332ac --- /dev/null +++ b/resources/3rdparty/gmm-5.2/README @@ -0,0 +1,29 @@ +# Copyright (C) 1999-2017 Yves Renard +# +# This file is a part of GetFEM++ +# +# GetFEM++ is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version along with the GCC Runtime Library +# Exception either version 3.1 or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License and GCC Runtime Library Exception for more details. +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Please read BUGS, INSTALL + + + +IMAGES and documentation : + +# Permission is granted to copy, distribute and/or modify all +# documentations and images included in GetFEM++ package +# under the terms of the GNU Free Documentation License, Version 1.3 +# or any later version published by the Free Software Foundation; +# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +# A copy of the license is included in top directory. diff --git a/resources/3rdparty/gmm-5.0/aclocal.m4 b/resources/3rdparty/gmm-5.2/aclocal.m4 similarity index 100% rename from resources/3rdparty/gmm-5.0/aclocal.m4 rename to resources/3rdparty/gmm-5.2/aclocal.m4 diff --git a/resources/3rdparty/gmm-5.0/compile b/resources/3rdparty/gmm-5.2/compile similarity index 100% rename from resources/3rdparty/gmm-5.0/compile rename to resources/3rdparty/gmm-5.2/compile diff --git a/resources/3rdparty/gmm-5.0/config.guess b/resources/3rdparty/gmm-5.2/config.guess similarity index 100% rename from resources/3rdparty/gmm-5.0/config.guess rename to resources/3rdparty/gmm-5.2/config.guess diff --git a/resources/3rdparty/gmm-5.0/config.h.in b/resources/3rdparty/gmm-5.2/config.h.in similarity index 100% rename from resources/3rdparty/gmm-5.0/config.h.in rename to resources/3rdparty/gmm-5.2/config.h.in diff --git a/resources/3rdparty/gmm-5.0/config.sub b/resources/3rdparty/gmm-5.2/config.sub similarity index 100% rename from resources/3rdparty/gmm-5.0/config.sub rename to resources/3rdparty/gmm-5.2/config.sub diff --git a/resources/3rdparty/gmm-5.0/configure b/resources/3rdparty/gmm-5.2/configure similarity index 99% rename from resources/3rdparty/gmm-5.0/configure rename to resources/3rdparty/gmm-5.2/configure index f4cff78f2..e7ffc50ec 100755 --- a/resources/3rdparty/gmm-5.0/configure +++ b/resources/3rdparty/gmm-5.2/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for gmm 5.0. +# Generated by GNU Autoconf 2.69 for gmm 5.2. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='gmm' PACKAGE_TARNAME='gmm' -PACKAGE_VERSION='5.0' -PACKAGE_STRING='gmm 5.0' +PACKAGE_VERSION='5.2' +PACKAGE_STRING='gmm 5.2' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1323,7 +1323,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures gmm 5.0 to adapt to many kinds of systems. +\`configure' configures gmm 5.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1393,7 +1393,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of gmm 5.0:";; + short | recursive ) echo "Configuration of gmm 5.2:";; esac cat <<\_ACEOF @@ -1501,7 +1501,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -gmm configure 5.0 +gmm configure 5.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1987,7 +1987,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by gmm $as_me 5.0, which was +It was created by gmm $as_me 5.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2335,7 +2335,7 @@ program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` PACKAGE="gmm" MAJOR_VERSION="5" -MINOR_VERSION="0" +MINOR_VERSION="2" VERSION=$MAJOR_VERSION.$MINOR_VERSION echo "configuring $PACKAGE $VERSION..." @@ -2845,7 +2845,7 @@ fi # Define the identity of the package. PACKAGE='gmm' - VERSION='5.0' + VERSION='5.2' cat >>confdefs.h <<_ACEOF @@ -15895,7 +15895,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by gmm $as_me 5.0, which was +This file was extended by gmm $as_me 5.2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -15961,7 +15961,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -gmm config.status 5.0 +gmm config.status 5.2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/resources/3rdparty/gmm-5.0/configure.ac b/resources/3rdparty/gmm-5.2/configure.ac similarity index 99% rename from resources/3rdparty/gmm-5.0/configure.ac rename to resources/3rdparty/gmm-5.2/configure.ac index 24442ff3a..6cf4f080d 100644 --- a/resources/3rdparty/gmm-5.0/configure.ac +++ b/resources/3rdparty/gmm-5.2/configure.ac @@ -8,14 +8,14 @@ dnl thus, updating cache ./config.cache avoided. define([AC_CACHE_LOAD], )dnl define([AC_CACHE_SAVE], )dnl -AC_INIT(gmm, 5.0) +AC_INIT(gmm, 5.2) AC_CONFIG_HEADERS(config.h) AC_PREREQ(2.56) AC_ARG_PROGRAM PACKAGE="gmm" MAJOR_VERSION="5" -MINOR_VERSION="0" +MINOR_VERSION="2" dnl VERSION=$MAJOR_VERSION.$MINOR_VERSION VERSION=$MAJOR_VERSION.$MINOR_VERSION echo "configuring $PACKAGE $VERSION..." diff --git a/resources/3rdparty/gmm-5.0/depcomp b/resources/3rdparty/gmm-5.2/depcomp similarity index 100% rename from resources/3rdparty/gmm-5.0/depcomp rename to resources/3rdparty/gmm-5.2/depcomp diff --git a/resources/3rdparty/gmm-5.0/gmm-config.in b/resources/3rdparty/gmm-5.2/gmm-config.in old mode 100755 new mode 100644 similarity index 67% rename from resources/3rdparty/gmm-5.0/gmm-config.in rename to resources/3rdparty/gmm-5.2/gmm-config.in index dba878d48..347a99f3b --- a/resources/3rdparty/gmm-5.0/gmm-config.in +++ b/resources/3rdparty/gmm-5.2/gmm-config.in @@ -1,5 +1,25 @@ #!/bin/sh # @configure_input@ + +# Copyright (C) 1999-2017 Yves Renard +# +# This file is a part of GetFEM++ +# +# GetFEM++ is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version along with the GCC Runtime Library +# Exception either version 3.1 or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License and GCC Runtime Library Exception for more details. +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + + + prefix="@prefix@" exec_prefix="@exec_prefix@" includedir="@includedir@" diff --git a/resources/3rdparty/gmm-5.0/include/Makefile.am b/resources/3rdparty/gmm-5.2/include/Makefile.am similarity index 100% rename from resources/3rdparty/gmm-5.0/include/Makefile.am rename to resources/3rdparty/gmm-5.2/include/Makefile.am index 9ed1298ff..5de6f84ff 100644 --- a/resources/3rdparty/gmm-5.0/include/Makefile.am +++ b/resources/3rdparty/gmm-5.2/include/Makefile.am @@ -1,6 +1,4 @@ nobase_include_HEADERS=\ - gmm/gmm.h\ - gmm/gmm_MUMPS_interface.h\ gmm/gmm_algobase.h\ gmm/gmm_blas.h\ gmm/gmm_blas_interface.h\ @@ -14,9 +12,10 @@ nobase_include_HEADERS=\ gmm/gmm_dense_sylvester.h\ gmm/gmm_domain_decomp.h\ gmm/gmm_except.h\ + gmm/gmm.h\ gmm/gmm_inoutput.h\ - gmm/gmm_interface.h\ gmm/gmm_interface_bgeot.h\ + gmm/gmm_interface.h\ gmm/gmm_iter.h\ gmm/gmm_iter_solvers.h\ gmm/gmm_kernel.h\ @@ -24,9 +23,10 @@ nobase_include_HEADERS=\ gmm/gmm_least_squares_cg.h\ gmm/gmm_matrix.h\ gmm/gmm_modified_gram_schmidt.h\ + gmm/gmm_MUMPS_interface.h\ gmm/gmm_opt.h\ - gmm/gmm_precond.h\ gmm/gmm_precond_diagonal.h\ + gmm/gmm_precond.h\ gmm/gmm_precond_ildlt.h\ gmm/gmm_precond_ildltt.h\ gmm/gmm_precond_ilu.h\ @@ -37,7 +37,6 @@ nobase_include_HEADERS=\ gmm/gmm_real_part.h\ gmm/gmm_ref.h\ gmm/gmm_scaled.h\ - gmm/gmm_solver_Schwarz_additive.h\ gmm/gmm_solver_bfgs.h\ gmm/gmm_solver_bicgstab.h\ gmm/gmm_solver_cg.h\ @@ -45,6 +44,7 @@ nobase_include_HEADERS=\ gmm/gmm_solver_gmres.h\ gmm/gmm_solver_idgmres.h\ gmm/gmm_solver_qmr.h\ + gmm/gmm_solver_Schwarz_additive.h\ gmm/gmm_std.h\ gmm/gmm_sub_index.h\ gmm/gmm_sub_matrix.h\ diff --git a/resources/3rdparty/gmm-5.0/include/Makefile.in b/resources/3rdparty/gmm-5.2/include/Makefile.in similarity index 100% rename from resources/3rdparty/gmm-5.0/include/Makefile.in rename to resources/3rdparty/gmm-5.2/include/Makefile.in index a7a0ed4ed..502026c76 100644 --- a/resources/3rdparty/gmm-5.0/include/Makefile.in +++ b/resources/3rdparty/gmm-5.2/include/Makefile.in @@ -286,8 +286,6 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ nobase_include_HEADERS = \ - gmm/gmm.h\ - gmm/gmm_MUMPS_interface.h\ gmm/gmm_algobase.h\ gmm/gmm_blas.h\ gmm/gmm_blas_interface.h\ @@ -301,9 +299,10 @@ nobase_include_HEADERS = \ gmm/gmm_dense_sylvester.h\ gmm/gmm_domain_decomp.h\ gmm/gmm_except.h\ + gmm/gmm.h\ gmm/gmm_inoutput.h\ - gmm/gmm_interface.h\ gmm/gmm_interface_bgeot.h\ + gmm/gmm_interface.h\ gmm/gmm_iter.h\ gmm/gmm_iter_solvers.h\ gmm/gmm_kernel.h\ @@ -311,9 +310,10 @@ nobase_include_HEADERS = \ gmm/gmm_least_squares_cg.h\ gmm/gmm_matrix.h\ gmm/gmm_modified_gram_schmidt.h\ + gmm/gmm_MUMPS_interface.h\ gmm/gmm_opt.h\ - gmm/gmm_precond.h\ gmm/gmm_precond_diagonal.h\ + gmm/gmm_precond.h\ gmm/gmm_precond_ildlt.h\ gmm/gmm_precond_ildltt.h\ gmm/gmm_precond_ilu.h\ @@ -324,7 +324,6 @@ nobase_include_HEADERS = \ gmm/gmm_real_part.h\ gmm/gmm_ref.h\ gmm/gmm_scaled.h\ - gmm/gmm_solver_Schwarz_additive.h\ gmm/gmm_solver_bfgs.h\ gmm/gmm_solver_bicgstab.h\ gmm/gmm_solver_cg.h\ @@ -332,6 +331,7 @@ nobase_include_HEADERS = \ gmm/gmm_solver_gmres.h\ gmm/gmm_solver_idgmres.h\ gmm/gmm_solver_qmr.h\ + gmm/gmm_solver_Schwarz_additive.h\ gmm/gmm_std.h\ gmm/gmm_sub_index.h\ gmm/gmm_sub_matrix.h\ diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm.h similarity index 93% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm.h index 8554d0342..feeb299fa 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_MUMPS_interface.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_MUMPS_interface.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_MUMPS_interface.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_MUMPS_interface.h index 45cc771e5..bc68777fc 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_MUMPS_interface.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_MUMPS_interface.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard, Julien Pommier - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard, Julien Pommier + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_MUMPS_interface.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_algobase.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_algobase.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_algobase.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_algobase.h index 3040665d7..64a859da1 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_algobase.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_algobase.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2000-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2000-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /** @file gmm_algobase.h @@ -110,7 +110,9 @@ namespace gmm { int i; for ( ; b1 != e1 && b2 != e2; ++b1, ++b2) if ((i = c(*b1, *b2)) != 0) return i; - if (b1 != e1) return 1; if (b2 != e2) return -1; return 0; + if (b1 != e1) return 1; + if (b2 != e2) return -1; + return 0; } template > diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_blas.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_blas.h similarity index 85% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_blas.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_blas.h index 4c7d82866..19e58f755 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_blas.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_blas.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_blas.h @@ -38,16 +38,17 @@ #ifndef GMM_BLAS_H__ #define GMM_BLAS_H__ -// This Version of GMM was modified for StoRM. -// To detect whether the usage of TBB is possible, this include is neccessary +// This Version of gmm++ was modified for Storm. +// To detect whether the usage of TBB is possible, this include is neccessary. #include "storm-config.h" #ifdef STORM_HAVE_INTELTBB -# include // This fixes a potential dependency ordering problem between GMM and TBB -# include "tbb/tbb.h" -# include +#include // This fixes a potential dependency ordering problem between GMM and TBB +#include "tbb/tbb.h" +#include #endif + #include "gmm_scaled.h" #include "gmm_transposed.h" #include "gmm_conjugated.h" @@ -79,9 +80,8 @@ namespace gmm { { return nnz(l, typename linalg_traits::linalg_type()); } ///@cond DOXY_SHOW_ALL_FUNCTIONS - template inline size_type nnz(const L& l, abstract_vector) { - typename linalg_traits::const_iterator it = vect_const_begin(l), - ite = vect_const_end(l); + template inline size_type nnz(const L& l, abstract_vector) { + auto it = vect_const_begin(l), ite = vect_const_end(l); size_type res(0); for (; it != ite; ++it) ++res; return res; @@ -444,10 +444,8 @@ namespace gmm { typename strongest_value_type::value_type vect_sp(const V1 &v1, const V2 &v2, abstract_skyline, abstract_skyline) { typedef typename strongest_value_type::value_type T; - typename linalg_traits::const_iterator it1 = vect_const_begin(v1), - ite1 = vect_const_end(v1); - typename linalg_traits::const_iterator it2 = vect_const_begin(v2), - ite2 = vect_const_end(v2); + auto it1 = vect_const_begin(v1), ite1 = vect_const_end(v1); + auto it2 = vect_const_begin(v2), ite2 = vect_const_end(v2); size_type n = std::min(ite1.index(), ite2.index()); size_type l = std::max(it1.index(), it2.index()); @@ -557,8 +555,7 @@ namespace gmm { vect_norm2_sqr(const V &v) { typedef typename linalg_traits::value_type T; typedef typename number_traits::magnitude_type R; - typename linalg_traits::const_iterator - it = vect_const_begin(v), ite = vect_const_end(v); + auto it = vect_const_begin(v), ite = vect_const_end(v); R res(0); for (; it != ite; ++it) res += gmm::abs_sqr(*it); return res; @@ -579,10 +576,8 @@ namespace gmm { vect_dist2_sqr(const V1 &v1, const V2 &v2) { // not fully optimized typedef typename linalg_traits::value_type T; typedef typename number_traits::magnitude_type R; - typename linalg_traits::const_iterator - it1 = vect_const_begin(v1), ite1 = vect_const_end(v1); - typename linalg_traits::const_iterator - it2 = vect_const_begin(v2), ite2 = vect_const_end(v2); + auto it1 = vect_const_begin(v1), ite1 = vect_const_end(v1); + auto it2 = vect_const_begin(v2), ite2 = vect_const_end(v2); size_type k1(0), k2(0); R res(0); while (it1 != ite1 && it2 != ite2) { @@ -660,8 +655,7 @@ namespace gmm { typename number_traits::value_type> ::magnitude_type vect_norm1(const V &v) { - typename linalg_traits::const_iterator - it = vect_const_begin(v), ite = vect_const_end(v); + auto it = vect_const_begin(v), ite = vect_const_end(v); typename number_traits::value_type> ::magnitude_type res(0); for (; it != ite; ++it) res += gmm::abs(*it); @@ -676,10 +670,9 @@ namespace gmm { typename number_traits::value_type> ::magnitude_type vect_norminf(const V &v) { - typename linalg_traits::const_iterator - it = vect_const_begin(v), ite = vect_const_end(v); - typename number_traits::value_type> - ::magnitude_type res(0); + auto it = vect_const_begin(v), ite = vect_const_end(v); + typename number_traits::value_type> + ::magnitude_type res(0); for (; it != ite; ++it) res = std::max(res, gmm::abs(*it)); return res; } @@ -709,10 +702,8 @@ namespace gmm { std::vector aux(mat_ncols(m)); for (size_type i = 0; i < mat_nrows(m); ++i) { - typedef typename linalg_traits::const_sub_row_type row_type; - row_type row = mat_const_row(m, i); - typename linalg_traits::const_iterator - it = vect_const_begin(row), ite = vect_const_end(row); + typename linalg_traits::const_sub_row_type row = mat_const_row(m, i); + auto it = vect_const_begin(row), ite = vect_const_end(row); for (size_type k = 0; it != ite; ++it, ++k) aux[index_of_it(it, k, store_type())] += gmm::abs(*it); } @@ -765,10 +756,8 @@ namespace gmm { std::vector aux(mat_nrows(m)); for (size_type i = 0; i < mat_ncols(m); ++i) { - typedef typename linalg_traits::const_sub_col_type col_type; - col_type col = mat_const_col(m, i); - typename linalg_traits::const_iterator - it = vect_const_begin(col), ite = vect_const_end(col); + typename linalg_traits::const_sub_col_type col = mat_const_col(m, i); + auto it = vect_const_begin(col), ite = vect_const_end(col); for (size_type k = 0; it != ite; ++it, ++k) aux[index_of_it(it, k, store_type())] += gmm::abs(*it); } @@ -843,7 +832,7 @@ namespace gmm { template void clean(L &l, double threshold, abstract_dense, T) { typedef typename number_traits::magnitude_type R; - typename linalg_traits::iterator it = vect_begin(l), ite = vect_end(l); + auto it = vect_begin(l), ite = vect_end(l); for (; it != ite; ++it) if (gmm::abs(*it) < R(threshold)) *it = T(0); } @@ -855,7 +844,7 @@ namespace gmm { template void clean(L &l, double threshold, abstract_sparse, T) { typedef typename number_traits::magnitude_type R; - typename linalg_traits::iterator it = vect_begin(l), ite = vect_end(l); + auto it = vect_begin(l), ite = vect_end(l); std::vector ind; for (; it != ite; ++it) if (gmm::abs(*it) < R(threshold)) ind.push_back(it.index()); @@ -864,7 +853,7 @@ namespace gmm { template void clean(L &l, double threshold, abstract_dense, std::complex) { - typename linalg_traits::iterator it = vect_begin(l), ite = vect_end(l); + auto it = vect_begin(l), ite = vect_end(l); for (; it != ite; ++it){ if (gmm::abs((*it).real()) < T(threshold)) *it = std::complex(T(0), (*it).imag()); @@ -879,7 +868,7 @@ namespace gmm { template void clean(L &l, double threshold, abstract_sparse, std::complex) { - typename linalg_traits::iterator it = vect_begin(l), ite = vect_end(l); + auto it = vect_begin(l), ite = vect_end(l); std::vector ind; for (; it != ite; ++it) { bool r = (gmm::abs((*it).real()) < T(threshold)); @@ -972,18 +961,14 @@ namespace gmm { void copy_mat_by_row(const L1& l1, L2& l2) { size_type nbr = mat_nrows(l1); for (size_type i = 0; i < nbr; ++i) - copy_vect(mat_const_row(l1, i), mat_row(l2, i), - typename linalg_traits::storage_type(), - typename linalg_traits::storage_type()); + copy(mat_const_row(l1, i), mat_row(l2, i)); } template void copy_mat_by_col(const L1 &l1, L2 &l2) { size_type nbc = mat_ncols(l1); for (size_type i = 0; i < nbc; ++i) { - copy_vect(mat_const_col(l1, i), mat_col(l2, i), - typename linalg_traits::storage_type(), - typename linalg_traits::storage_type()); + copy(mat_const_col(l1, i), mat_col(l2, i)); } } @@ -1050,24 +1035,21 @@ namespace gmm { template void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_sparse) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) l2(i, it.index()) = *it; } template void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_skyline) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) l2(i, it.index()) = *it; } template void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_dense) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (size_type j = 0; it != ite; ++it, ++j) l2(i, j) = *it; } @@ -1078,22 +1060,19 @@ namespace gmm { template void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_sparse) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) l2(it.index(), i) = *it; } template void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_skyline) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) l2(it.index(), i) = *it; } template void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_dense) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (size_type j = 0; it != ite; ++it, ++j) l2(j, i) = *it; } @@ -1120,15 +1099,13 @@ namespace gmm { template inline // to be optimised ? void copy_vect(const L1 &l1, L2 &l2, abstract_skyline, abstract_skyline) { - typename linalg_traits::const_iterator it1 = vect_const_begin(l1), - ite1 = vect_const_end(l1); + auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); while (it1 != ite1 && *it1 == typename linalg_traits::value_type(0)) ++it1; if (ite1 - it1 > 0) { clear(l2); - typename linalg_traits::iterator it2 = vect_begin(l2), - ite2 = vect_end(l2); + auto it2 = vect_begin(l2), ite2 = vect_end(l2); while (*(ite1-1) == typename linalg_traits::value_type(0)) ite1--; if (it2 == ite2) { @@ -1155,29 +1132,25 @@ namespace gmm { template void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_dense) { clear(l2); - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) { l2[it.index()] = *it; } } template void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_skyline) { clear(l2); - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) l2[it.index()] = *it; } template void copy_vect(const L1& l1, L2& l2, abstract_skyline, abstract_dense) { typedef typename linalg_traits::value_type T; - typedef typename linalg_traits::const_iterator l1_const_iterator; - typedef typename linalg_traits::iterator l2_iterator; - l1_const_iterator it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); if (it == ite) gmm::clear(l2); else { - l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2); + auto it2 = vect_begin(l2), ite2 = vect_end(l2); size_type i = it.index(), j; for (j = 0; j < i; ++j, ++it2) *it2 = T(0); @@ -1188,19 +1161,21 @@ namespace gmm { template void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_sparse) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); clear(l2); - for (; it != ite; ++it) + // cout << "copy " << l1 << " of size " << vect_size(l1) << " nnz = " << nnz(l1) << endl; + for (; it != ite; ++it) { + // cout << "*it = " << *it << endl; + // cout << "it.index() = " << it.index() << endl; if (*it != (typename linalg_traits::value_type)(0)) l2[it.index()] = *it; + } } template void copy_vect(const L1& l1, L2& l2, abstract_dense, abstract_sparse) { clear(l2); - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (size_type i = 0; it != ite; ++it, ++i) if (*it != (typename linalg_traits::value_type)(0)) l2[i] = *it; @@ -1209,8 +1184,7 @@ namespace gmm { template // to be optimised ... void copy_vect(const L1& l1, L2& l2, abstract_dense, abstract_skyline) { clear(l2); - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (size_type i = 0; it != ite; ++it, ++i) if (*it != (typename linalg_traits::value_type)(0)) l2[i] = *it; @@ -1220,8 +1194,7 @@ namespace gmm { template void copy_vect(const L1& l1, L2& l2, abstract_skyline, abstract_sparse) { clear(l2); - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) if (*it != (typename linalg_traits::value_type)(0)) l2[it.index()] = *it; @@ -1258,25 +1231,24 @@ namespace gmm { template inline void add_spec(const L1& l1, L2& l2, abstract_matrix) { GMM_ASSERT2(mat_nrows(l1)==mat_nrows(l2) && mat_ncols(l1)==mat_ncols(l2), - "dimensions mismatch"); + "dimensions mismatch l1 is " << mat_nrows(l1) << "x" + << mat_ncols(l1) << " and l2 is " << mat_nrows(l2) + << "x" << mat_ncols(l2)); add(l1, l2, typename linalg_traits::sub_orientation(), typename linalg_traits::sub_orientation()); } template void add(const L1& l1, L2& l2, row_major, row_major) { - typename linalg_traits::const_row_iterator it1 = mat_row_begin(l1), - ite = mat_row_end(l1); - typename linalg_traits::row_iterator it2 = mat_row_begin(l2); + auto it1 = mat_row_begin(l1), ite = mat_row_end(l1); + auto it2 = mat_row_begin(l2); for ( ; it1 != ite; ++it1, ++it2) add(linalg_traits::row(it1), linalg_traits::row(it2)); } template void add(const L1& l1, L2& l2, col_major, col_major) { - typename linalg_traits::const_col_iterator - it1 = mat_col_const_begin(l1), - ite = mat_col_const_end(l1); + auto it1 = mat_col_const_begin(l1), ite = mat_col_const_end(l1); typename linalg_traits::col_iterator it2 = mat_col_begin(l2); for ( ; it1 != ite; ++it1, ++it2) add(linalg_traits::col(it1), linalg_traits::col(it2)); @@ -1289,22 +1261,19 @@ namespace gmm { template void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_sparse) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) l2(i, it.index()) += *it; } template void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_skyline) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) l2(i, it.index()) += *it; } template void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_dense) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (size_type j = 0; it != ite; ++it, ++j) l2(i, j) += *it; } @@ -1315,22 +1284,19 @@ namespace gmm { template void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_sparse) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) l2(it.index(), i) += *it; } template void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_skyline) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (; it != ite; ++it) l2(it.index(), i) += *it; } template void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_dense) { - typename linalg_traits::const_iterator - it = vect_const_begin(l1), ite = vect_const_end(l1); + auto it = vect_const_begin(l1), ite = vect_const_end(l1); for (size_type j = 0; it != ite; ++it, ++j) l2(j, i) += *it; } @@ -1490,10 +1456,8 @@ namespace gmm { template void add_spspsp(const L1& l1, const L2& l2, L3& l3, linalg_true) { - typename linalg_traits::const_iterator - it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); - typename linalg_traits::const_iterator - it2 = vect_const_begin(l2), ite2 = vect_const_end(l2); + auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); + auto it2 = vect_const_begin(l2), ite2 = vect_const_end(l2); clear(l3); while (it1 != ite1 && it2 != ite2) { ptrdiff_t d = it1.index() - it2.index(); @@ -1522,23 +1486,20 @@ namespace gmm { template void add(const L1& l1, L2& l2, abstract_dense, abstract_dense) { - typename linalg_traits::const_iterator it1 = vect_const_begin(l1); - typename linalg_traits::iterator - it2 = vect_begin(l2), ite = vect_end(l2); + auto it1 = vect_const_begin(l1); + auto it2 = vect_begin(l2), ite = vect_end(l2); for (; it2 != ite; ++it2, ++it1) *it2 += *it1; } template void add(const L1& l1, L2& l2, abstract_dense, abstract_skyline) { - typedef typename linalg_traits::const_iterator const_l1_iterator; - typedef typename linalg_traits::iterator l2_iterator; typedef typename linalg_traits::value_type T; - const_l1_iterator it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); + auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); size_type i1 = 0, ie1 = vect_size(l1); while (it1 != ite1 && *it1 == T(0)) { ++it1; ++i1; } if (it1 != ite1) { - l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2); + auto it2 = vect_begin(l2), ite2 = vect_end(l2); while (ie1 && *(ite1-1) == T(0)) { ite1--; --ie1; } if (it2 == ite2 || i1 < it2.index()) { @@ -1558,10 +1519,9 @@ namespace gmm { template void add(const L1& l1, L2& l2, abstract_skyline, abstract_dense) { - typename linalg_traits::const_iterator it1 = vect_const_begin(l1), - ite1 = vect_const_end(l1); + auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); if (it1 != ite1) { - typename linalg_traits::iterator it2 = vect_begin(l2); + auto it2 = vect_begin(l2); it2 += it1.index(); for (; it1 != ite1; ++it2, ++it1) *it2 += *it1; } @@ -1570,30 +1530,26 @@ namespace gmm { template void add(const L1& l1, L2& l2, abstract_sparse, abstract_dense) { - typename linalg_traits::const_iterator - it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); + auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); for (; it1 != ite1; ++it1) l2[it1.index()] += *it1; } template void add(const L1& l1, L2& l2, abstract_sparse, abstract_sparse) { - typename linalg_traits::const_iterator - it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); + auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); for (; it1 != ite1; ++it1) l2[it1.index()] += *it1; } template void add(const L1& l1, L2& l2, abstract_sparse, abstract_skyline) { - typename linalg_traits::const_iterator - it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); + auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); for (; it1 != ite1; ++it1) l2[it1.index()] += *it1; } template void add(const L1& l1, L2& l2, abstract_skyline, abstract_sparse) { - typename linalg_traits::const_iterator - it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); + auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); for (; it1 != ite1; ++it1) if (*it1 != typename linalg_traits::value_type(0)) l2[it1.index()] += *it1; @@ -1601,16 +1557,14 @@ namespace gmm { template void add(const L1& l1, L2& l2, abstract_skyline, abstract_skyline) { - typedef typename linalg_traits::const_iterator const_l1_iterator; - typedef typename linalg_traits::iterator l2_iterator; typedef typename linalg_traits::value_type T1; typedef typename linalg_traits::value_type T2; - const_l1_iterator it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); + auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); while (it1 != ite1 && *it1 == T1(0)) ++it1; if (ite1 != it1) { - l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2); + auto it2 = vect_begin(l2), ite2 = vect_end(l2); while (*(ite1-1) == T1(0)) ite1--; if (it2 == ite2 || it1.index() < it2.index()) { l2[it1.index()] = T2(0); @@ -1627,8 +1581,7 @@ namespace gmm { template void add(const L1& l1, L2& l2, abstract_dense, abstract_sparse) { - typename linalg_traits::const_iterator - it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); + auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); for (size_type i = 0; it1 != ite1; ++it1, ++i) if (*it1 != typename linalg_traits::value_type(0)) l2[i] += *it1; } @@ -1690,11 +1643,9 @@ namespace gmm { if (aux != T(0)) l3[i] = aux; } } - + #ifdef STORM_HAVE_INTELTBB - /* Official Intel Hint on blocked_range vs. linear iterators: http://software.intel.com/en-us/forums/topic/289505 - - */ + // Official Intel Hint on blocked_range vs. linear iterators: http://software.intel.com/en-us/forums/topic/289505 template class forward_range_mult { IT1 my_begin; @@ -1754,23 +1705,119 @@ namespace gmm { my_l2(l2) {} }; -#endif + + template + class tbbHelper_mult_add_by_row { + L2 const* my_l2; + L3 const* my_l3; + + // Typedefs for Iterator Types + typedef typename linalg_traits::iterator frm_IT1; + typedef typename linalg_traits::const_row_iterator frm_IT2; + typedef typename linalg_traits::const_iterator frm_IT3; + + public: + void operator()( const forward_range_mult& r ) const { + L2 const& l2 = *my_l2; + + frm_IT1 it = r.begin(); + frm_IT1 ite = r.end(); + frm_IT2 itr = r.begin_row(); + frm_IT3 addIt = my_l3->begin(); + + for (; it != ite; ++it, ++itr, ++addIt) { + *it = vect_sp(linalg_traits::row(itr), l2, + typename linalg_traits::storage_type(), + typename linalg_traits::storage_type()) + *addIt; + } + } + + tbbHelper_mult_add_by_row(L2 const* l2, L2 const* l3) : my_l2(l2), my_l3(l3) { + // Intentionally left empty. + } + }; + + template + class TbbMultFunctor { + public: + TbbMultFunctor(L1 const& l1, L2 const& l2, L3& l3) : l1(l1), l2(l2), l3(l3) { + // Intentionally left empty. + } + + void operator()(tbb::blocked_range const& range) const { + auto itr = mat_row_const_begin(l1) + range.begin(); + auto l2it = l2.begin() + range.begin(); + auto l3it = l3.begin() + range.begin(); + auto l3ite = l3.begin() + range.end(); + + for (; l3it != l3ite; ++l3it, ++l2it, ++itr) { + *l3it = vect_sp(linalg_traits::row(itr), l2, typename linalg_traits::storage_type(), typename linalg_traits::storage_type()); + } + } + + private: + L1 const& l1; + L2 const& l2; + L3& l3; + }; + + template + void mult_by_row_parallel(const L1& l1, const L2& l2, L3& l3, abstract_dense) { + tbb::parallel_for(tbb::blocked_range(0, vect_size(l3), 10), TbbMultFunctor(l1, l2, l3)); + } + + template + class TbbMultAddFunctor { + public: + TbbMultAddFunctor(L1 const& l1, L2 const& l2, L3 const& l3, L4& l4) : l1(l1), l2(l2), l3(l3), l4(l4) { + // Intentionally left empty. + } + + void operator()(tbb::blocked_range const& range) const { + auto itr = mat_row_const_begin(l1) + range.begin(); + auto l2it = l2.begin() + range.begin(); + auto l3it = l3.begin() + range.begin(); + auto l4it = l4.begin() + range.begin(); + auto l4ite = l4.begin() + range.end(); + + for (; l4it != l4ite; ++l4it, ++l3it, ++l2it, ++itr) { + *l4it = vect_sp(linalg_traits::row(itr), l2, typename linalg_traits::storage_type(), typename linalg_traits::storage_type()) + *l3it; + } + } + + private: + L1 const& l1; + L2 const& l2; + L3 const& l3; + L4& l4; + }; + + template + void mult_add_by_row_parallel(const L1& l1, const L2& l2, const L3& l3, L4& l4, abstract_dense) { + tbb::parallel_for(tbb::blocked_range(0, vect_size(l4), 10), TbbMultAddFunctor(l1, l2, l3, l4)); + } +#endif + template void mult_by_row(const L1& l1, const L2& l2, L3& l3, abstract_dense) { typename linalg_traits::iterator it=vect_begin(l3), ite=vect_end(l3); - typename linalg_traits::const_row_iterator - itr = mat_row_const_begin(l1); -#ifdef STORM_HAVE_INTELTBB - tbb::parallel_for(forward_range_mult::iterator, typename linalg_traits::const_row_iterator>(it, ite, itr), tbbHelper_mult_by_row(&l2)); -#else - for (; it != ite; ++it, ++itr) - *it = vect_sp(linalg_traits::row(itr), l2, - typename linalg_traits::storage_type(), - typename linalg_traits::storage_type()); -#endif + auto itr = mat_row_const_begin(l1); + for (; it != ite; ++it, ++itr) + *it = vect_sp(linalg_traits::row(itr), l2, + typename linalg_traits::storage_type(), + typename linalg_traits::storage_type()); } + template + void mult_by_row_bwd(const L1& l1, const L2& l2, L3& l3, abstract_dense) { + typename linalg_traits::iterator target_it=vect_end(l3) - 1, target_ite=vect_begin(l3) - 1; + typename linalg_traits::const_row_iterator + itr = mat_row_const_end(l1) - 1; + for (; target_it != target_ite; --target_it, --itr) + *target_it = vect_sp(linalg_traits::row(itr), l2); + } + template void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_dense) { clear(l3); @@ -1783,8 +1830,7 @@ namespace gmm { void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_sparse) { typedef typename linalg_traits::value_type T; clear(l3); - typename linalg_traits::const_iterator it = vect_const_begin(l2), - ite = vect_const_end(l2); + auto it = vect_const_begin(l2), ite = vect_const_end(l2); for (; it != ite; ++it) if (*it != T(0)) add(scaled(mat_const_col(l1, it.index()), *it), l3); } @@ -1793,8 +1839,7 @@ namespace gmm { void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_skyline) { typedef typename linalg_traits::value_type T; clear(l3); - typename linalg_traits::const_iterator it = vect_const_begin(l2), - ite = vect_const_end(l2); + auto it = vect_const_begin(l2), ite = vect_const_end(l2); for (; it != ite; ++it) if (*it != T(0)) add(scaled(mat_const_col(l1, it.index()), *it), l3); } @@ -1803,6 +1848,12 @@ namespace gmm { void mult_spec(const L1& l1, const L2& l2, L3& l3, row_major) { mult_by_row(l1, l2, l3, typename linalg_traits::storage_type()); } +#ifdef STORM_HAVE_INTELTBB + template inline + void mult_parallel_spec(const L1& l1, const L2& l2, L3& l3, row_major) + { mult_by_row_parallel(l1, l2, l3, typename linalg_traits::storage_type()); } +#endif + template inline void mult_spec(const L1& l1, const L2& l2, L3& l3, col_major) { mult_by_col(l1, l2, l3, typename linalg_traits::storage_type()); } @@ -1862,21 +1913,60 @@ namespace gmm { /** Multiply-accumulate. l4 = l1*l2 + l3; */ template inline void mult_add(const L1& l1, const L2& l2, const L3& l3, L4& l4) { - size_type m = mat_nrows(l1), n = mat_ncols(l1); - if (!m || !n) return; - GMM_ASSERT2(n==vect_size(l2) && m==vect_size(l3) && vect_size(l3) == vect_size(l4), "dimensions mismatch"); - if (!same_origin(l2, l3)) { - mult_add_spec(l1, l2, l3, l4, typename principal_orientation_type::sub_orientation>::potype()); - } - else { - GMM_WARNING2("Warning, A temporary is used for mult\n"); - typename temporary_vector::vector_type temp(vect_size(l2)); - copy(l2, temp); - mult_add_spec(l1, temp, l3, l4, typename principal_orientation_type::sub_orientation>::potype()); - } + size_type m = mat_nrows(l1), n = mat_ncols(l1); + if (!m || !n) return; + GMM_ASSERT2(n==vect_size(l2) && m==vect_size(l3) && vect_size(l3) == vect_size(l4), "dimensions mismatch"); + if (!same_origin(l2, l4) && !same_origin(l3, l4) && !same_origin(l2, l3)) { + mult_add_spec(l1, l2, l3, l4, typename principal_orientation_type::sub_orientation>::potype()); + } else { + GMM_WARNING2("Warning, Multiple temporaries are used for mult\n"); + typename temporary_vector::vector_type l2tmp(vect_size(l2)); + copy(l2, l2tmp); + typename temporary_vector::vector_type l3tmp(vect_size(l3)); + copy(l3, l3tmp); + mult_add_spec(l1, l2tmp, l3tmp, l4, typename principal_orientation_type::sub_orientation>::potype()); + } } + +#ifdef STORM_HAVE_INTELTBB + /** Multiply. l3 = l1*l2; */ + template inline + void mult_parallel(const L1& l1, const L2& l2, L3& l3) { + size_type m = mat_nrows(l1), n = mat_ncols(l1); + if (!m || !n) return; + GMM_ASSERT2(n==vect_size(l2), "dimensions mismatch"); + if (!same_origin(l2, l3)) { + mult_parallel_spec(l1, l2, l3, typename principal_orientation_type::sub_orientation>::potype()); + } else { + GMM_WARNING2("Warning, temporaries are used for mult\n"); + typename temporary_vector::vector_type l2tmp(vect_size(l2)); + copy(l2, l2tmp); + mult_parallel_spec(l1, l2tmp, l3, typename principal_orientation_type::sub_orientation>::potype()); + } + } + + /** Multiply-accumulate. l4 = l1*l2 + l3; */ + template inline + void mult_add_parallel(const L1& l1, const L2& l2, const L3& l3, L4& l4) { + size_type m = mat_nrows(l1), n = mat_ncols(l1); + if (!m || !n) return; + GMM_ASSERT2(n==vect_size(l2) && m==vect_size(l3) && vect_size(l3) == vect_size(l4), "dimensions mismatch"); + if (!same_origin(l2, l4) && !same_origin(l3, l4) && !same_origin(l2, l3)) { + mult_add_parallel_spec(l1, l2, l3, l4, typename principal_orientation_type::sub_orientation>::potype()); + } else { + GMM_WARNING2("Warning, Multiple temporaries are used for mult\n"); + typename temporary_vector::vector_type l2tmp(vect_size(l2)); + copy(l2, l2tmp); + typename temporary_vector::vector_type l3tmp(vect_size(l3)); + copy(l3, l3tmp); + mult_add_parallel_spec(l1, l2tmp, l3tmp, l4, typename principal_orientation_type::sub_orientation>::potype()); + } + } +#endif ///@cond DOXY_SHOW_ALL_FUNCTIONS template inline @@ -1905,23 +1995,32 @@ namespace gmm { template void mult_add_by_row(const L1& l1, const L2& l2, L3& l3, abstract_dense) { - typename linalg_traits::iterator it=vect_begin(l3), ite=vect_end(l3); - typename linalg_traits::const_row_iterator - itr = mat_row_const_begin(l1); + auto it=vect_begin(l3), ite=vect_end(l3); + auto itr = mat_row_const_begin(l1); for (; it != ite; ++it, ++itr) *it += vect_sp(linalg_traits::row(itr), l2); } - + template void mult_add_by_row(const L1& l1, const L2& l2, const L3& l3, L4& l4, abstract_dense) { - typename linalg_traits::const_iterator add_it=vect_begin(l3), add_ite=vect_end(l3); - typename linalg_traits::iterator target_it=vect_begin(l4), target_ite=vect_end(l4); - typename linalg_traits::const_row_iterator - itr = mat_row_const_begin(l1); - for (; add_it != add_ite; ++add_it, ++target_it, ++itr) - *target_it = vect_sp(linalg_traits::row(itr), l2) + *add_it; + typename linalg_traits::const_iterator add_it=vect_begin(l3), add_ite=vect_end(l3); + typename linalg_traits::iterator target_it=vect_begin(l4), target_ite=vect_end(l4); + typename linalg_traits::const_row_iterator + itr = mat_row_const_begin(l1); + for (; add_it != add_ite; ++add_it, ++target_it, ++itr) + *target_it = vect_sp(linalg_traits::row(itr), l2) + *add_it; } + template + void mult_add_by_row_bwd(const L1& l1, const L2& l2, const L3& l3, L4& l4, abstract_dense) { + typename linalg_traits::const_iterator add_it=vect_end(l3) - 1, add_ite=vect_begin(l3) - 1; + typename linalg_traits::iterator target_it=vect_end(l4) - 1, target_ite=vect_begin(l4) - 1; + typename linalg_traits::const_row_iterator + itr = mat_row_const_end(l1) - 1; + for (; add_it != add_ite; --add_it, --target_it, --itr) + *target_it = vect_sp(linalg_traits::row(itr), l2) + *add_it; + } + template void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_dense) { size_type nc = mat_ncols(l1); @@ -1931,8 +2030,7 @@ namespace gmm { template void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_sparse) { - typename linalg_traits::const_iterator it = vect_const_begin(l2), - ite = vect_const_end(l2); + auto it = vect_const_begin(l2), ite = vect_const_end(l2); for (; it != ite; ++it) if (*it != typename linalg_traits::value_type(0)) add(scaled(mat_const_col(l1, it.index()), *it), l3); @@ -1940,8 +2038,7 @@ namespace gmm { template void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_skyline) { - typename linalg_traits::const_iterator it = vect_const_begin(l2), - ite = vect_const_end(l2); + auto it = vect_const_begin(l2), ite = vect_const_end(l2); for (; it != ite; ++it) if (*it != typename linalg_traits::value_type(0)) add(scaled(mat_const_col(l1, it.index()), *it), l3); @@ -1954,7 +2051,13 @@ namespace gmm { template inline void mult_add_spec(const L1& l1, const L2& l2, const L3& l3, L4& l4, row_major) { mult_add_by_row(l1, l2, l3, l4, typename linalg_traits::storage_type()); } - + +#ifdef STORM_HAVE_INTELTBB + template inline + void mult_add_parallel_spec(const L1& l1, const L2& l2, const L3& l3, L4& l4, row_major) + { mult_add_by_row_parallel(l1, l2, l3, l4, typename linalg_traits::storage_type()); } +#endif + template inline void mult_add_spec(const L1& l1, const L2& l2, L3& l3, col_major) { mult_add_by_col(l1, l2, l3, typename linalg_traits::storage_type()); } @@ -2113,8 +2216,7 @@ namespace gmm { linalg_traits::sub_orientation>::potype()); } else { - typename linalg_traits::const_col_iterator - it2b = linalg_traits::col_begin(l2), it2, + auto it2b = linalg_traits::col_begin(l2), it2 = it2b, ite = linalg_traits::col_end(l2); size_type i,j, k = mat_nrows(l1); @@ -2152,8 +2254,7 @@ namespace gmm { size_type nn = mat_nrows(l3); for (size_type i = 0; i < nn; ++i) { typename linalg_traits::const_sub_row_type rl1=mat_const_row(l1, i); - typename linalg_traits::const_sub_row_type>:: - const_iterator it = vect_const_begin(rl1), ite = vect_const_end(rl1); + auto it = vect_const_begin(rl1), ite = vect_const_end(rl1); for (; it != ite; ++it) add(scaled(mat_const_row(l2, it.index()), *it), mat_row(l3, i)); } @@ -2194,9 +2295,8 @@ namespace gmm { clear(l3); size_type nn = mat_ncols(l3); for (size_type i = 0; i < nn; ++i) { - typename linalg_traits::const_sub_col_type rc2=mat_const_col(l2, i); - typename linalg_traits::const_sub_col_type>:: - const_iterator it = vect_const_begin(rc2), ite = vect_const_end(rc2); + typename linalg_traits::const_sub_col_type rc2 = mat_const_col(l2, i); + auto it = vect_const_begin(rc2), ite = vect_const_end(rc2); for (; it != ite; ++it) add(scaled(mat_const_col(l1, it.index()), *it), mat_col(l3, i)); } @@ -2246,9 +2346,8 @@ namespace gmm { clear(l3); size_type nn = mat_ncols(l1); for (size_type i = 0; i < nn; ++i) { - typename linalg_traits::const_sub_col_type rc1=mat_const_col(l1, i); - typename linalg_traits::const_sub_col_type>:: - const_iterator it = vect_const_begin(rc1), ite = vect_const_end(rc1); + typename linalg_traits::const_sub_col_type rc1 = mat_const_col(l1, i); + auto it = vect_const_begin(rc1), ite = vect_const_end(rc1); for (; it != ite; ++it) add(scaled(mat_const_row(l2, i), *it), mat_row(l3, it.index())); } @@ -2299,10 +2398,8 @@ namespace gmm { bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol, row_major) { for (size_type i = 0; i < mat_nrows(A); ++i) { - typedef typename linalg_traits::const_sub_row_type row_type; - row_type row = mat_const_row(A, i); - typename linalg_traits::const_iterator - it = vect_const_begin(row), ite = vect_const_end(row); + typename linalg_traits::const_sub_row_type row = mat_const_row(A, i); + auto it = vect_const_begin(row), ite = vect_const_end(row); for (; it != ite; ++it) if (gmm::abs(*it - A(it.index(), i)) > tol) return false; } @@ -2313,10 +2410,8 @@ namespace gmm { bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol, col_major) { for (size_type i = 0; i < mat_ncols(A); ++i) { - typedef typename linalg_traits::const_sub_col_type col_type; - col_type col = mat_const_col(A, i); - typename linalg_traits::const_iterator - it = vect_const_begin(col), ite = vect_const_end(col); + typename linalg_traits::const_sub_col_type col = mat_const_col(A, i); + auto it = vect_const_begin(col), ite = vect_const_end(col); for (; it != ite; ++it) if (gmm::abs(*it - A(i, it.index())) > tol) return false; } @@ -2364,10 +2459,8 @@ namespace gmm { bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol, row_major) { for (size_type i = 0; i < mat_nrows(A); ++i) { - typedef typename linalg_traits::const_sub_row_type row_type; - row_type row = mat_const_row(A, i); - typename linalg_traits::const_iterator - it = vect_const_begin(row), ite = vect_const_end(row); + typename linalg_traits::const_sub_row_type row = mat_const_row(A, i); + auto it = vect_const_begin(row), ite = vect_const_end(row); for (; it != ite; ++it) if (gmm::abs(gmm::conj(*it) - A(it.index(), i)) > tol) return false; } @@ -2378,10 +2471,8 @@ namespace gmm { bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol, col_major) { for (size_type i = 0; i < mat_ncols(A); ++i) { - typedef typename linalg_traits::const_sub_col_type col_type; - col_type col = mat_const_col(A, i); - typename linalg_traits::const_iterator - it = vect_const_begin(col), ite = vect_const_end(col); + typename linalg_traits::const_sub_col_type col = mat_const_col(A, i); + auto it = vect_const_begin(col), ite = vect_const_end(col); for (; it != ite; ++it) if (gmm::abs(gmm::conj(*it) - A(i, it.index())) > tol) return false; } diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_blas_interface.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_blas_interface.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_blas_interface.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_blas_interface.h index 563c39d1a..c41ae95d3 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_blas_interface.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_blas_interface.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_blas_interface.h @@ -47,6 +47,8 @@ namespace gmm { + // Use ./configure --enable-blas-interface to activate this interface. + #define GMMLAPACK_TRACE(f) // #define GMMLAPACK_TRACE(f) cout << "function " << f << " called" << endl; @@ -168,16 +170,18 @@ namespace gmm { void sger_(...); void dger_(...); void cgerc_(...); void zgerc_(...); } +#if 1 + /* ********************************************************************* */ /* vect_norm2(x). */ /* ********************************************************************* */ - # define nrm2_interface(param1, trans1, blas_name, base_type) \ - inline number_traits::magnitude_type \ - vect_norm2(param1(base_type)) { \ - GMMLAPACK_TRACE("nrm2_interface"); \ - int inc(1), n(int(vect_size(x))); trans1(base_type); \ - return blas_name(&n, &x[0], &inc); \ +# define nrm2_interface(param1, trans1, blas_name, base_type) \ + inline number_traits::magnitude_type \ + vect_norm2(param1(base_type)) { \ + GMMLAPACK_TRACE("nrm2_interface"); \ + int inc(1), n(int(vect_size(x))); trans1(base_type); \ + return blas_name(&n, &x[0], &inc); \ } # define nrm2_p1(base_type) const std::vector &x @@ -192,7 +196,7 @@ namespace gmm { /* vect_sp(x, y). */ /* ********************************************************************* */ - # define dot_interface(param1, trans1, mult1, param2, trans2, mult2, \ +# define dot_interface(param1, trans1, mult1, param2, trans2, mult2, \ blas_name, base_type) \ inline base_type vect_sp(param1(base_type), param2(base_type)) { \ GMMLAPACK_TRACE("dot_interface"); \ @@ -259,8 +263,8 @@ namespace gmm { /* vect_hp(x, y). */ /* ********************************************************************* */ - # define dotc_interface(param1, trans1, mult1, param2, trans2, mult2, \ - blas_name, base_type) \ +# define dotc_interface(param1, trans1, mult1, param2, trans2, mult2, \ + blas_name, base_type) \ inline base_type vect_hp(param1(base_type), param2(base_type)) { \ GMMLAPACK_TRACE("dotc_interface"); \ trans1(base_type); trans2(base_type); int inc(1), n(int(vect_size(y)));\ @@ -329,6 +333,7 @@ namespace gmm { inline void add(param1(base_type), std::vector &y) { \ GMMLAPACK_TRACE("axpy_interface"); \ int inc(1), n(int(vect_size(y))); trans1(base_type); \ + if (n == 0) return; \ blas_name(&n, &a, &x[0], &inc, &y[0], &inc); \ } @@ -690,7 +695,7 @@ namespace gmm { # define gemm_interface_nt(blas_name, base_type, is_const) \ inline void mult_spec(const dense_matrix &A, \ - const transposed_col_ref *> &B_,\ + const transposed_col_ref *> &B_, \ dense_matrix &C, r_mult) { \ GMMLAPACK_TRACE("gemm_interface_nt"); \ dense_matrix &B \ @@ -721,9 +726,9 @@ namespace gmm { # define gemm_interface_tt(blas_name, base_type, isA_const, isB_const) \ inline void mult_spec( \ - const transposed_col_ref *> &A_,\ - const transposed_col_ref *> &B_,\ - dense_matrix &C, r_mult) { \ + const transposed_col_ref *> &A_, \ + const transposed_col_ref *> &B_, \ + dense_matrix &C, r_mult) { \ GMMLAPACK_TRACE("gemm_interface_tt"); \ dense_matrix &A \ = const_cast &>(*(linalg_origin(A_))); \ @@ -935,6 +940,7 @@ namespace gmm { trsv_interface(upper_tri_solve, trsv_lower, gem_p1_c, gem_trans1_c, ztrsv_, BLAS_Z) +#endif } #endif // GMM_BLAS_INTERFACE_H diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_condition_number.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_condition_number.h similarity index 94% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_condition_number.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_condition_number.h index a9e25f568..0dac20e6b 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_condition_number.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_condition_number.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard, Julien Pommier - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard, Julien Pommier + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_condition_number.h @@ -60,6 +60,10 @@ namespace gmm { typedef typename linalg_traits::value_type T; typedef typename number_traits::magnitude_type R; + // Added because of errors in complex with zero det + if (sizeof(T) != sizeof(R) && gmm::abs(gmm::lu_det(M)) == R(0)) + return gmm::default_max(R()); + size_type m = mat_nrows(M), n = mat_ncols(M); emax = emin = R(0); std::vector eig(m+n); diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_conjugated.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_conjugated.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_conjugated.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_conjugated.h index 35948f0c8..1e3e7fc61 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_conjugated.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_conjugated.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_conjugated.h @@ -195,40 +195,6 @@ namespace gmm { { return gmm::conj(linalg_traits::access(begin_+j, i)); } }; - template - struct linalg_traits > { - typedef conjugated_row_matrix_const_ref this_type; - typedef typename linalg_traits::origin_type origin_type; - typedef linalg_const is_reference; - typedef abstract_matrix linalg_type; - typedef typename linalg_traits::value_type value_type; - typedef value_type reference; - typedef typename linalg_traits::storage_type storage_type; - typedef typename linalg_traits::const_sub_row_type vector_type; - typedef conjugated_vector_const_ref sub_col_type; - typedef conjugated_vector_const_ref const_sub_col_type; - typedef conjugated_row_const_iterator col_iterator; - typedef conjugated_row_const_iterator const_col_iterator; - typedef abstract_null_type const_sub_row_type; - typedef abstract_null_type sub_row_type; - typedef abstract_null_type const_row_iterator; - typedef abstract_null_type row_iterator; - typedef col_major sub_orientation; - typedef typename linalg_traits::index_sorted index_sorted; - static inline size_type ncols(const this_type &m) { return m.nc; } - static inline size_type nrows(const this_type &m) { return m.nr; } - static inline const_sub_col_type col(const const_col_iterator &it) - { return conjugated(linalg_traits::row(it.it)); } - static inline const_col_iterator col_begin(const this_type &m) - { return const_col_iterator(m.begin_); } - static inline const_col_iterator col_end(const this_type &m) - { return const_col_iterator(m.end_); } - static inline const origin_type* origin(const this_type &m) - { return m.origin; } - static value_type access(const const_col_iterator &it, size_type i) - { return gmm::conj(linalg_traits::access(it.it, i)); } - }; - template std::ostream &operator << (std::ostream &o, const conjugated_row_matrix_const_ref& m) { gmm::write(o,m); return o; } @@ -287,39 +253,7 @@ namespace gmm { { return gmm::conj(linalg_traits::access(begin_+i, j)); } }; - template - struct linalg_traits > { - typedef conjugated_col_matrix_const_ref this_type; - typedef typename linalg_traits::origin_type origin_type; - typedef linalg_const is_reference; - typedef abstract_matrix linalg_type; - typedef typename linalg_traits::value_type value_type; - typedef value_type reference; - typedef typename linalg_traits::storage_type storage_type; - typedef typename linalg_traits::const_sub_col_type vector_type; - typedef conjugated_vector_const_ref sub_row_type; - typedef conjugated_vector_const_ref const_sub_row_type; - typedef conjugated_col_const_iterator row_iterator; - typedef conjugated_col_const_iterator const_row_iterator; - typedef abstract_null_type const_sub_col_type; - typedef abstract_null_type sub_col_type; - typedef abstract_null_type const_col_iterator; - typedef abstract_null_type col_iterator; - typedef row_major sub_orientation; - typedef typename linalg_traits::index_sorted index_sorted; - static inline size_type nrows(const this_type &m) { return m.nr; } - static inline size_type ncols(const this_type &m) { return m.nc; } - static inline const_sub_row_type row(const const_row_iterator &it) - { return conjugated(linalg_traits::col(it.it)); } - static inline const_row_iterator row_begin(const this_type &m) - { return const_row_iterator(m.begin_); } - static inline const_row_iterator row_end(const this_type &m) - { return const_row_iterator(m.end_); } - static inline const origin_type* origin(const this_type &m) - { return m.origin; } - static value_type access(const const_row_iterator &it, size_type i) - { return gmm::conj(linalg_traits::access(it.it, i)); } - }; + template std::ostream &operator << (std::ostream &o, const conjugated_col_matrix_const_ref& m) @@ -387,6 +321,74 @@ namespace gmm { template inline conjugated_col_matrix_const_ref conjugated(const L &v, col_major) { return conjugated_col_matrix_const_ref(v); } + + template + struct linalg_traits > { + typedef conjugated_row_matrix_const_ref this_type; + typedef typename linalg_traits::origin_type origin_type; + typedef linalg_const is_reference; + typedef abstract_matrix linalg_type; + typedef typename linalg_traits::value_type value_type; + typedef value_type reference; + typedef typename linalg_traits::storage_type storage_type; + typedef typename org_type::const_sub_row_type>::t vector_type; + typedef conjugated_vector_const_ref sub_col_type; + typedef conjugated_vector_const_ref const_sub_col_type; + typedef conjugated_row_const_iterator col_iterator; + typedef conjugated_row_const_iterator const_col_iterator; + typedef abstract_null_type const_sub_row_type; + typedef abstract_null_type sub_row_type; + typedef abstract_null_type const_row_iterator; + typedef abstract_null_type row_iterator; + typedef col_major sub_orientation; + typedef typename linalg_traits::index_sorted index_sorted; + static inline size_type ncols(const this_type &m) { return m.nc; } + static inline size_type nrows(const this_type &m) { return m.nr; } + static inline const_sub_col_type col(const const_col_iterator &it) + { return conjugated(linalg_traits::row(it.it)); } + static inline const_col_iterator col_begin(const this_type &m) + { return const_col_iterator(m.begin_); } + static inline const_col_iterator col_end(const this_type &m) + { return const_col_iterator(m.end_); } + static inline const origin_type* origin(const this_type &m) + { return m.origin; } + static value_type access(const const_col_iterator &it, size_type i) + { return gmm::conj(linalg_traits::access(it.it, i)); } + }; + + template + struct linalg_traits > { + typedef conjugated_col_matrix_const_ref this_type; + typedef typename linalg_traits::origin_type origin_type; + typedef linalg_const is_reference; + typedef abstract_matrix linalg_type; + typedef typename linalg_traits::value_type value_type; + typedef value_type reference; + typedef typename linalg_traits::storage_type storage_type; + typedef typename org_type::const_sub_col_type>::t vector_type; + typedef conjugated_vector_const_ref sub_row_type; + typedef conjugated_vector_const_ref const_sub_row_type; + typedef conjugated_col_const_iterator row_iterator; + typedef conjugated_col_const_iterator const_row_iterator; + typedef abstract_null_type const_sub_col_type; + typedef abstract_null_type sub_col_type; + typedef abstract_null_type const_col_iterator; + typedef abstract_null_type col_iterator; + typedef row_major sub_orientation; + typedef typename linalg_traits::index_sorted index_sorted; + static inline size_type nrows(const this_type &m) { return m.nr; } + static inline size_type ncols(const this_type &m) { return m.nc; } + static inline const_sub_row_type row(const const_row_iterator &it) + { return conjugated(linalg_traits::col(it.it)); } + static inline const_row_iterator row_begin(const this_type &m) + { return const_row_iterator(m.begin_); } + static inline const_row_iterator row_end(const this_type &m) + { return const_row_iterator(m.end_); } + static inline const origin_type* origin(const this_type &m) + { return m.origin; } + static value_type access(const const_row_iterator &it, size_type i) + { return gmm::conj(linalg_traits::access(it.it, i)); } + }; ///@endcond diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_def.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_def.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_def.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_def.h index b5471e1a1..603c57b69 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_def.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_def.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_def.h @@ -221,23 +221,33 @@ namespace gmm { }; /* ******************************************************************** */ - /* types to deal with const object representing a modifiable reference */ + /* Original type from a pointer or a reference. */ + /* ******************************************************************** */ + + template struct org_type { typedef V t; }; + template struct org_type { typedef V t; }; + template struct org_type { typedef V t; }; + template struct org_type { typedef V t; }; + template struct org_type { typedef V t; }; + + /* ******************************************************************** */ + /* Types to deal with const object representing a modifiable reference */ /* ******************************************************************** */ template struct mref_type_ { typedef abstract_null_type return_type; }; template struct mref_type_ - { typedef L & return_type; }; + { typedef typename org_type::t & return_type; }; template struct mref_type_ - { typedef const L & return_type; }; + { typedef const typename org_type::t & return_type; }; template struct mref_type_ - { typedef const L & return_type; }; + { typedef const typename org_type::t & return_type; }; template struct mref_type_ - { typedef const L & return_type; }; + { typedef const typename org_type::t & return_type; }; template struct mref_type_ - { typedef L & return_type; }; + { typedef typename org_type::t & return_type; }; template struct mref_type_ - { typedef L & return_type; }; + { typedef typename org_type::t & return_type; }; template struct mref_type { typedef typename std::iterator_traits::value_type L; @@ -255,7 +265,7 @@ namespace gmm { template struct cref_type_ { typedef abstract_null_type return_type; }; template struct cref_type_ - { typedef L & return_type; }; + { typedef typename org_type::t & return_type; }; template struct cref_type { typedef typename cref_type_::is_reference>::return_type return_type; @@ -409,13 +419,6 @@ namespace gmm { # define magnitude_of_linalg(M) typename number_traits::value_type>::magnitude_type - template inline std::complex operator*(const std::complex& a, int b) { - return a*T(b); - } - template inline std::complex operator*(int b, const std::complex& a) { - return a*T(b); - } - /* ******************************************************************** */ /* types promotion */ /* ******************************************************************** */ @@ -483,6 +486,7 @@ namespace gmm { template class wsvector; template class rsvector; + template class dsvector; template struct sparse_vector_type { typedef wsvector vector_type; }; diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_Householder.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_Householder.h similarity index 96% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_Householder.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_Householder.h index c662bc96c..4dcb3cd24 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_Householder.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_Householder.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard, Caroline Lecalvez - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard, Caroline Lecalvez + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_dense_Householder.h @@ -59,7 +59,7 @@ namespace gmm { for (size_type i = 0; i < N; ++i, ++itx) { typedef typename linalg_traits::sub_row_type row_type; row_type row = mat_row(A, i); - typename linalg_traits::iterator + typename linalg_traits::t>::iterator it = vect_begin(row), ite = vect_end(row); typename linalg_traits::const_iterator ity = vect_const_begin(y); T tx = *itx; @@ -78,7 +78,7 @@ namespace gmm { for (size_type i = 0; i < M; ++i, ++ity) { typedef typename linalg_traits::sub_col_type col_type; col_type col = mat_col(A, i); - typename linalg_traits::iterator + typename linalg_traits::t>::iterator it = vect_begin(col), ite = vect_end(col); typename linalg_traits::const_iterator itx = vect_const_begin(x); T ty = *ity; @@ -112,7 +112,7 @@ namespace gmm { for (size_type i = 0; i < N; ++i, ++itx1, ++ity2) { typedef typename linalg_traits::sub_row_type row_type; row_type row = mat_row(A, i); - typename linalg_traits::iterator + typename linalg_traits::t>::iterator it = vect_begin(row), ite = vect_end(row); typename linalg_traits::const_iterator itx2 = vect_const_begin(x); typename linalg_traits::const_iterator ity1 = vect_const_begin(y); @@ -134,7 +134,7 @@ namespace gmm { for (size_type i = 0; i < M; ++i, ++ity1, ++itx2) { typedef typename linalg_traits::sub_col_type col_type; col_type col = mat_col(A, i); - typename linalg_traits::iterator + typename linalg_traits::t>::iterator it = vect_begin(col), ite = vect_end(col); typename linalg_traits::const_iterator itx1 = vect_const_begin(x); typename linalg_traits::const_iterator ity2 = vect_const_begin(y); diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_lu.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_lu.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_lu.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_lu.h index 88db4d215..5107abebf 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_lu.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_lu.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ // This file is a modified version of lu.h from MTL. @@ -112,7 +112,7 @@ namespace gmm { rank_one_update(sub_matrix(A, sub_interval(j+1, M-j-1), sub_interval(j+1, N-j-1)), c, conjugated(r)); } - ipvt[j] = int_T(j + 1); + ipvt[NN-1] = int_T(NN); } return info; } diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_matrix_functions.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_matrix_functions.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_matrix_functions.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_matrix_functions.h index 460980263..6005918a4 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_matrix_functions.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_matrix_functions.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - Copyright (C) 2014-2015 Konstantinos Poulios + Copyright (C) 2014-2017 Konstantinos Poulios - This file is a part of GETFEM++ + This file is a part of GetFEM++ - Getfem++ is free software; you can redistribute it and/or modify it + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_qr.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_qr.h similarity index 99% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_qr.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_qr.h index 299f90c9b..9de7dbeb8 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_qr.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_qr.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_dense_qr.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_sylvester.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_sylvester.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_sylvester.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_sylvester.h index 5d65d9986..3b184ccbf 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_dense_sylvester.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_dense_sylvester.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /** @file gmm_dense_sylvester.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_domain_decomp.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_domain_decomp.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_domain_decomp.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_domain_decomp.h index 82108dfaa..2821f3a09 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_domain_decomp.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_domain_decomp.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2004-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2004-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /** @file gmm_domain_decomp.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_except.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_except.h similarity index 86% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_except.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_except.h index 3848657d5..30b813a26 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_except.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_except.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /** @file gmm_except.h @@ -39,15 +39,15 @@ #ifndef GMM_EXCEPT_H__ #define GMM_EXCEPT_H__ +#include "gmm_std.h" + //provides external implementation of gmm_exception and logging. #ifndef EXTERNAL_EXCEPT_ -#include "gmm_std.h" - namespace gmm { /* *********************************************************************** */ -/* Getfem++ generic errors. */ +/* GetFEM++ generic errors. */ /* *********************************************************************** */ class gmm_error: public std::logic_error { @@ -69,14 +69,14 @@ namespace gmm { // defined. // GMM_ASSERT3 : For internal checks. Hidden by default. Active // only when DEBUG_MODE is defined. -// __EXCEPTIONS is defined by gcc, _CPPUNWIND is defined by visual c++ + // __EXCEPTIONS is defined by gcc, _CPPUNWIND is defined by visual c++ #if defined(__EXCEPTIONS) || defined(_CPPUNWIND) inline void short_error_throw(const char *file, int line, const char *func, const char *errormsg) { std::stringstream msg__; msg__ << "Error in " << file << ", line " << line << " " << func << ": \n" << errormsg << std::ends; - throw gmm::gmm_error(msg__.str()); + throw gmm::gmm_error(msg__.str()); } # define GMM_THROW_(type, errormsg) { \ std::stringstream msg__; \ @@ -115,7 +115,6 @@ namespace gmm { # define GMM_ASSERT1(test, errormsg) \ { if (!(test)) GMM_THROW_(gmm::gmm_error, errormsg); } - // inline void GMM_THROW() IS_DEPRECATED; inline void GMM_THROW() {} #define GMM_THROW(a, b) { GMM_THROW_(a,b); gmm::GMM_THROW(); } @@ -134,7 +133,7 @@ namespace gmm { #endif /* *********************************************************************** */ -/* Getfem++ warnings. */ +/* GetFEM++ warnings. */ /* *********************************************************************** */ // This allows to dynamically hide warnings @@ -195,7 +194,7 @@ namespace gmm { #endif /* *********************************************************************** */ -/* Getfem++ traces. */ +/* GetFEM++ traces. */ /* *********************************************************************** */ // This allows to dynamically hide traces @@ -262,66 +261,51 @@ namespace gmm { /* Definitions for compatibility with old versions. */ /* ********************************************************************* */ - using std::invalid_argument; - - struct dimension_error : public std::logic_error - { dimension_error(const std::string& w): std::logic_error(w) {} }; - struct file_not_found_error : public std::logic_error - { file_not_found_error(const std::string& w): std::logic_error (w) {} }; - struct internal_error : public std::logic_error - { internal_error(const std::string& w): std::logic_error(w) {} }; - struct failure_error : public std::logic_error - { failure_error(const std::string& w): std::logic_error (w) {} }; - struct not_linear_error : public std::logic_error - { not_linear_error(const std::string& w): std::logic_error (w) {} }; - struct to_be_done_error : public std::logic_error - { to_be_done_error(const std::string& w): std::logic_error (w) {} }; - -#define GMM_STANDARD_CATCH_ERROR catch(std::logic_error e) \ - { \ +#define GMM_STANDARD_CATCH_ERROR catch(std::logic_error e) \ + { \ std::cerr << "============================================\n"; \ std::cerr << "| An error has been detected !!! |\n"; \ std::cerr << "============================================\n"; \ - std::cerr << e.what() << std::endl << std::endl; \ - exit(1); \ - } \ - catch(std::runtime_error e) \ - { \ + std::cerr << e.what() << std::endl << std::endl; \ + exit(1); \ + } \ + catch(const std::runtime_error &e) \ + { \ std::cerr << "============================================\n"; \ std::cerr << "| An error has been detected !!! |\n"; \ std::cerr << "============================================\n"; \ - std::cerr << e.what() << std::endl << std::endl; \ - exit(1); \ - } \ - catch(std::bad_alloc) { \ + std::cerr << e.what() << std::endl << std::endl; \ + exit(1); \ + } \ + catch(const std::bad_alloc &) { \ std::cerr << "============================================\n"; \ std::cerr << "| A bad allocation has been detected !!! |\n"; \ std::cerr << "============================================\n"; \ - exit(1); \ - } \ - catch(std::bad_typeid) { \ + exit(1); \ + } \ + catch(const std::bad_typeid &) { \ std::cerr << "============================================\n"; \ std::cerr << "| A bad typeid has been detected !!! |\n"; \ std::cerr << "============================================\n"; \ - exit(1); \ - } \ - catch(std::bad_exception) { \ + exit(1); \ + } \ + catch(const std::bad_exception &) { \ std::cerr << "============================================\n"; \ std::cerr << "| A bad exception has been detected !!! |\n"; \ std::cerr << "============================================\n"; \ - exit(1); \ - } \ - catch(std::bad_cast) { \ + exit(1); \ + } \ + catch(const std::bad_cast &) { \ std::cerr << "============================================\n"; \ std::cerr << "| A bad cast has been detected !!! |\n"; \ std::cerr << "============================================\n"; \ - exit(1); \ - } \ - catch(...) { \ + exit(1); \ + } \ + catch(...) { \ std::cerr << "============================================\n"; \ std::cerr << "| An unknown error has been detected !!! |\n"; \ std::cerr << "============================================\n"; \ - exit(1); \ + exit(1); \ } // catch(ios_base::failure) { // std::cerr << "============================================\n"; diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_inoutput.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_inoutput.h similarity index 99% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_inoutput.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_inoutput.h index 56aaed741..0e27b17cc 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_inoutput.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_inoutput.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard, Julien Pommier - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard, Julien Pommier + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_inoutput.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_interface.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_interface.h similarity index 99% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_interface.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_interface.h index e887780ce..a3c66cd1b 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_interface.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_interface.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ @@ -194,6 +194,12 @@ namespace gmm { std::ostream &operator << (std::ostream &o, const simple_vector_ref& v) { gmm::write(o,v); return o; } + template + simple_vector_ref *> + vref(const std::vector &vv) + { return simple_vector_ref *>(vv); } + + /* ********************************************************************* */ /* */ /* Traits for S.T.L. object */ @@ -230,12 +236,9 @@ namespace gmm { { return it[i]; } static void resize(this_type &v, size_type n) { v.resize(n); } }; -} - -namespace gmm { - template std::ostream &operator << - (std::ostream &o, const std::vector& m) { gmm::write(o,m); return o; } + + template inline size_type nnz(const std::vector& l) { return l.size(); } diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_interface_bgeot.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_interface_bgeot.h similarity index 96% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_interface_bgeot.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_interface_bgeot.h index 20a5c8de6..d1d0ae3ab 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_interface_bgeot.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_interface_bgeot.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_interface_bgeot.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_iter.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_iter.h similarity index 91% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_iter.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_iter.h index 3ce187507..e82d270f4 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_iter.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_iter.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_iter.h @@ -111,17 +111,23 @@ namespace gmm { double get_rhsnorm(void) const { return rhsn; } void set_rhsnorm(double r) { rhsn = r; } - bool converged(void) { return res <= rhsn * resmax; } + bool converged(void) { + return !isnan(res) && res <= rhsn * resmax; + } bool converged(double nr) { - res = gmm::abs(nr); resminreach = std::min(resminreach, res); + res = gmm::abs(nr); + resminreach = std::min(resminreach, res); return converged(); } template bool converged(const VECT &v) { return converged(gmm::vect_norm2(v)); } - bool diverged(void) - { return (nit>=maxiter) || (res>=rhsn*diverged_res && nit > 4); } - bool diverged(double nr) { - res = gmm::abs(nr); resminreach = std::min(resminreach, res); + bool diverged(void) { + return isnan(res) || (nit>=maxiter) + || (res>=rhsn*diverged_res && nit > 4); + } + bool diverged(double nr) { + res = gmm::abs(nr); + resminreach = std::min(resminreach, res); return diverged(); } diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_iter_solvers.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_iter_solvers.h similarity index 95% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_iter_solvers.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_iter_solvers.h index aabc2fdd0..cb34ef088 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_iter_solvers.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_iter_solvers.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_iter_solvers.h @@ -70,7 +70,8 @@ namespace gmm { c = std::max(a, b); a = std::min(a, b); b = c; while (d > tol) { c = b - (b - a) * (Gb / (Gb - Ga)); /* regula falsi. */ - if (c > b) c = b; if (c < a) c = a; + if (c > b) c = b; + if (c < a) c = a; Gc = G(c); if (Gc*Gb > 0) { b = c; Gb = Gc; } else { a = c; Ga = Gc; } c = (b + a) / 2.0 ; Gc = G(c); /* Dichotomie. */ diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_kernel.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_kernel.h similarity index 93% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_kernel.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_kernel.h index 046dad0bc..ebd217610 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_kernel.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_kernel.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_kernel.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_lapack_interface.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_lapack_interface.h similarity index 96% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_lapack_interface.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_lapack_interface.h index d146dc7af..7888aea05 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_lapack_interface.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_lapack_interface.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_lapack_interface.h @@ -149,14 +149,11 @@ namespace gmm { void lu_inverse(const dense_matrix &LU, \ std::vector &ipvt, const dense_matrix &A_) { \ GMMLAPACK_TRACE("getri_interface"); \ - dense_matrix& \ - A = const_cast &>(A_); \ - int n = int(mat_nrows(A)), info, lwork(-1); base_type work1; \ + dense_matrix &A \ + = const_cast &>(A_); \ + int n = int(mat_nrows(A)), info, lwork(10000); base_type work[10000]; \ if (n) { \ - gmm::copy(LU, A); \ - lapack_name(&n, &A(0,0), &n, &ipvt[0], &work1, &lwork, &info); \ - lwork = int(gmm::real(work1)); \ - std::vector work(lwork); \ + std::copy(LU.begin(), LU.end(), A.begin()); \ lapack_name(&n, &A(0,0), &n, &ipvt[0], &work[0], &lwork, &info); \ } \ } @@ -199,8 +196,8 @@ namespace gmm { GMMLAPACK_TRACE("geqrf_interface2"); \ int m = int(mat_nrows(A)), n = int(mat_ncols(A)), info, lwork(-1); \ base_type work1; \ - if (m && n) { \ - gmm::copy(A, Q); \ + if (m && n) { \ + std::copy(A.begin(), A.end(), Q.begin()); \ std::vector tau(n); \ lapack_name1(&m, &n, &Q(0,0), &m, &tau[0], &work1 , &lwork, &info); \ lwork = int(gmm::real(work1)); \ diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_least_squares_cg.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_least_squares_cg.h similarity index 95% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_least_squares_cg.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_least_squares_cg.h index 09e061526..71e446658 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_least_squares_cg.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_least_squares_cg.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard, Benjamin Schleimer - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard, Benjamin Schleimer + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_leastsquares_cg.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_matrix.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_matrix.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_matrix.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_matrix.h index 54cc024cd..23fb9d267 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_matrix.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_matrix.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /** @file gmm_matrix.h @@ -193,8 +193,8 @@ namespace gmm typedef typename linalg_traits::value_type value_type; typedef typename linalg_traits::reference reference; typedef typename linalg_traits::storage_type storage_type; - typedef simple_vector_ref sub_row_type; - typedef simple_vector_ref const_sub_row_type; + typedef V & sub_row_type; + typedef const V & const_sub_row_type; typedef typename std::vector::iterator row_iterator; typedef typename std::vector::const_iterator const_row_iterator; typedef abstract_null_type sub_col_type; @@ -299,8 +299,8 @@ namespace gmm typedef typename linalg_traits::value_type value_type; typedef typename linalg_traits::reference reference; typedef typename linalg_traits::storage_type storage_type; - typedef simple_vector_ref sub_col_type; - typedef simple_vector_ref const_sub_col_type; + typedef V &sub_col_type; + typedef const V &const_sub_col_type; typedef typename std::vector::iterator col_iterator; typedef typename std::vector::const_iterator const_col_iterator; typedef abstract_null_type sub_row_type; @@ -318,9 +318,9 @@ namespace gmm static const_col_iterator col_end(const this_type &m) { return m.end(); } static const_sub_col_type col(const const_col_iterator &it) - { return const_sub_col_type(*it); } + { return *it; } static sub_col_type col(const col_iterator &it) - { return sub_col_type(*it); } + { return *it; } static origin_type* origin(this_type &m) { return &m; } static const origin_type* origin(const this_type &m) { return &m; } static void do_clear(this_type &m) { m.clear_mat(); } @@ -369,6 +369,7 @@ namespace gmm const std::vector &as_vector(void) const { return *this; } void resize(size_type, size_type); + void base_resize(size_type, size_type); void reshape(size_type, size_type); void fill(T a, T b = T(0)); @@ -387,6 +388,10 @@ namespace gmm nbl = m; nbc = n; } + template void dense_matrix::base_resize(size_type m, + size_type n) + { std::vector::resize(n*m); nbl = m; nbc = n; } + template void dense_matrix::resize(size_type m, size_type n) { if (n*m > nbc*nbl) std::vector::resize(n*m); if (m < nbl) { @@ -546,7 +551,7 @@ namespace gmm ir.resize(jc[nc]); for (size_type j = 0; j < nc; ++j) { col_type col = mat_const_col(B, j); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(col), ite = vect_const_end(col); for (size_type k = 0; it != ite; ++it, ++k) { pr[jc[j]-shift+k] = *it; @@ -696,7 +701,7 @@ namespace gmm ir.resize(jc[nr]); for (size_type j = 0; j < nr; ++j) { row_type row = mat_const_row(B, j); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(row), ite = vect_const_end(row); for (size_type k = 0; it != ite; ++it, ++k) { pr[jc[j]-shift+k] = *it; diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_modified_gram_schmidt.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_modified_gram_schmidt.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_modified_gram_schmidt.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_modified_gram_schmidt.h index 86c18360f..34d54ae3f 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_modified_gram_schmidt.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_modified_gram_schmidt.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ //=========================================================================== diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_opt.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_opt.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_opt.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_opt.h index 7a3cb2e2f..e73af4153 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_opt.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_opt.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_opt.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond.h similarity index 95% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_precond.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_precond.h index 3e5fb20c6..fca4f35d4 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2004-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2004-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ #ifndef GMM_PRECOND_H #define GMM_PRECOND_H diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_diagonal.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_diagonal.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_diagonal.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_diagonal.h index 91dff1d55..19d46095b 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_diagonal.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_diagonal.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_precond_diagonal.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ildlt.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ildlt.h similarity index 82% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ildlt.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ildlt.h index 060c99c88..22484df73 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ildlt.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ildlt.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ // This file is a modified version of cholesky.h from ITL. @@ -144,7 +144,7 @@ namespace gmm { for (Tri_loc = 0, i = 0; i < n; ++i) { typedef typename linalg_traits::const_sub_row_type row_type; row_type row = mat_const_row(A, i); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(row), ite = vect_const_end(row); if (count) { Tri_val[Tri_loc] = T(0); Tri_ind[Tri_loc] = i; } @@ -235,51 +235,6 @@ namespace gmm { { copy(v1, v2); gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); } - - // for compatibility with old versions - - template - struct cholesky_precond : public ildlt_precond { - cholesky_precond(const Matrix& A) : ildlt_precond(A) {} - cholesky_precond(void) {} - } IS_DEPRECATED; - - template inline - void mult(const cholesky_precond& P, const V1 &v1, V2 &v2) { - gmm::copy(v1, v2); - gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); - for (size_type i = 0; i < mat_nrows(P.U); ++i) v2[i] /= P.D(i); - gmm::upper_tri_solve(P.U, v2, true); - } - - template inline - void transposed_mult(const cholesky_precond& P,const V1 &v1,V2 &v2) - { mult(P, v1, v2); } - - template inline - void left_mult(const cholesky_precond& P, const V1 &v1, V2 &v2) { - copy(v1, v2); - gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); - for (size_type i = 0; i < mat_nrows(P.U); ++i) v2[i] /= P.D(i); - } - - template inline - void right_mult(const cholesky_precond& P, const V1 &v1, V2 &v2) - { copy(v1, v2); gmm::upper_tri_solve(P.U, v2, true); } - - template inline - void transposed_left_mult(const cholesky_precond& P, const V1 &v1, - V2 &v2) { - copy(v1, v2); - gmm::upper_tri_solve(P.U, v2, true); - for (size_type i = 0; i < mat_nrows(P.U); ++i) v2[i] /= P.D(i); - } - - template inline - void transposed_right_mult(const cholesky_precond& P, const V1 &v1, - V2 &v2) - { copy(v1, v2); gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); } - } #endif diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ildltt.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ildltt.h similarity index 77% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ildltt.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ildltt.h index f0fac0a5c..380106a40 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ildltt.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ildltt.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_precond_ildltt.h @@ -168,52 +168,6 @@ namespace gmm { V2 &v2) { copy(v1, v2); gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); } - - // for compatibility with old versions - - template - struct choleskyt_precond : public ildltt_precond{ - choleskyt_precond(const Matrix& A, int k_, double eps_) - : ildltt_precond(A, k_, eps_) {} - choleskyt_precond(void) {} - } IS_DEPRECATED; - - template inline - void mult(const choleskyt_precond& P, const V1 &v1, V2 &v2) { - gmm::copy(v1, v2); - gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); - for (size_type i = 0; i < P.indiag.size(); ++i) v2[i] *= P.indiag[i]; - gmm::upper_tri_solve(P.U, v2, true); - } - - template inline - void transposed_mult(const choleskyt_precond& P,const V1 &v1, V2 &v2) - { mult(P, v1, v2); } - - template inline - void left_mult(const choleskyt_precond& P, const V1 &v1, V2 &v2) { - copy(v1, v2); - gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); - for (size_type i = 0; i < P.indiag.size(); ++i) v2[i] *= P.indiag[i]; - } - - template inline - void right_mult(const choleskyt_precond& P, const V1 &v1, V2 &v2) - { copy(v1, v2); gmm::upper_tri_solve(P.U, v2, true); } - - template inline - void transposed_left_mult(const choleskyt_precond& P, const V1 &v1, - V2 &v2) { - copy(v1, v2); - gmm::upper_tri_solve(P.U, v2, true); - for (size_type i = 0; i < P.indiag.size(); ++i) v2[i] *= P.indiag[i]; - } - - template inline - void transposed_right_mult(const choleskyt_precond& P, const V1 &v1, - V2 &v2) - { copy(v1, v2); gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); } - } #endif diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ilu.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ilu.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ilu.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ilu.h index b529aa0cd..9256b86a2 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ilu.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ilu.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ // This file is a modified version of ilu.h from ITL. @@ -142,7 +142,7 @@ namespace gmm { for (i = 0; i < n; ++i) { typedef typename linalg_traits::const_sub_row_type row_type; row_type row = mat_const_row(A, i); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(row), ite = vect_const_end(row); if (count) { U_val[U_loc] = T(0); U_ind[U_loc] = i; } diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ilut.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ilut.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ilut.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ilut.h index a57612633..0860324f0 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ilut.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ilut.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ // This file is a modified version of ilut.h from ITL. diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ilutp.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ilutp.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ilutp.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ilutp.h index 98eae3724..d867d6053 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_ilutp.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_ilutp.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2004-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2004-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_precond_ilutp.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_mr_approx_inverse.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_mr_approx_inverse.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_mr_approx_inverse.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_mr_approx_inverse.h index 41d9da3d7..7504f48fb 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_precond_mr_approx_inverse.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_precond_mr_approx_inverse.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_range_basis.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_range_basis.h similarity index 99% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_range_basis.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_range_basis.h index 68eafd5ee..05a71a0c8 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_range_basis.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_range_basis.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2009-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2009-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_range_basis.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_real_part.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_real_part.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_real_part.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_real_part.h index 089bdc35c..c4e61d815 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_real_part.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_real_part.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_real_part.h @@ -237,7 +237,163 @@ namespace gmm { typedef typename linalg_traits::V_reference ref_t; set_to_end(it.it, o, typename linalg_traits::pV(), ref_t()); } + + template std::ostream &operator << + (std::ostream &o, const part_vector& m) + { gmm::write(o,m); return o; } + + + /* ********************************************************************* */ + /* Reference to the real or imaginary part of (complex) matrices */ + /* ********************************************************************* */ + + + template struct part_row_ref { + + typedef part_row_ref this_type; + typedef typename std::iterator_traits::value_type M; + typedef M * CPT; + typedef typename std::iterator_traits::reference ref_M; + typedef typename select_ref + ::const_row_iterator, typename linalg_traits + ::row_iterator, PT>::ref_type iterator; + typedef typename linalg_traits::value_type value_type; + typedef typename linalg_traits::reference reference; + typedef typename linalg_traits::porigin_type porigin_type; + + iterator begin_, end_; + porigin_type origin; + size_type nr, nc; + + part_row_ref(ref_M m) + : begin_(mat_row_begin(m)), end_(mat_row_end(m)), + origin(linalg_origin(m)), nr(mat_nrows(m)), nc(mat_ncols(m)) {} + + part_row_ref(const part_row_ref &cr) : + begin_(cr.begin_),end_(cr.end_), origin(cr.origin),nr(cr.nr),nc(cr.nc) {} + + reference operator()(size_type i, size_type j) const { + return reference(ref_or_value_type::r( + linalg_traits::access(begin_+i, j), + PART(), value_type())); + } + }; + + template std::ostream &operator << + (std::ostream &o, const part_row_ref& m) + { gmm::write(o,m); return o; } + + template struct part_col_ref { + + typedef part_col_ref this_type; + typedef typename std::iterator_traits::value_type M; + typedef M * CPT; + typedef typename std::iterator_traits::reference ref_M; + typedef typename select_ref + ::const_col_iterator, typename linalg_traits + ::col_iterator, PT>::ref_type iterator; + typedef typename linalg_traits::value_type value_type; + typedef typename linalg_traits::reference reference; + typedef typename linalg_traits::porigin_type porigin_type; + + iterator begin_, end_; + porigin_type origin; + size_type nr, nc; + + part_col_ref(ref_M m) + : begin_(mat_col_begin(m)), end_(mat_col_end(m)), + origin(linalg_origin(m)), nr(mat_nrows(m)), nc(mat_ncols(m)) {} + + part_col_ref(const part_col_ref &cr) : + begin_(cr.begin_),end_(cr.end_), origin(cr.origin),nr(cr.nr),nc(cr.nc) {} + + reference operator()(size_type i, size_type j) const { + return reference(ref_or_value_type::r( + linalg_traits::access(begin_+j, i), + PART(), value_type())); + } + }; + + + + template std::ostream &operator << + (std::ostream &o, const part_col_ref& m) + { gmm::write(o,m); return o; } + + + + + +template + struct part_return_ { + typedef abstract_null_type return_type; + }; + template + struct part_return_ { + typedef typename std::iterator_traits::value_type L; + typedef typename select_return, + part_row_ref< L *, PART>, PT>::return_type return_type; + }; + template + struct part_return_ { + typedef typename std::iterator_traits::value_type L; + typedef typename select_return, + part_col_ref, PT>::return_type return_type; + }; + + template struct part_return__{ + typedef abstract_null_type return_type; + }; + + template + struct part_return__ { + typedef typename std::iterator_traits::value_type L; + typedef typename part_return_::sub_orientation>::potype, PART, + PT>::return_type return_type; + }; + + template + struct part_return__ { + typedef typename std::iterator_traits::value_type L; + typedef typename select_return, + part_vector, PT>::return_type return_type; + }; + + template struct part_return { + typedef typename std::iterator_traits::value_type L; + typedef typename part_return__::linalg_type>::return_type return_type; + }; + + template inline + typename part_return::return_type + real_part(const L &l) { + return typename part_return::return_type + (linalg_cast(const_cast(l))); + } + + template inline + typename part_return::return_type + real_part(L &l) { + return typename part_return::return_type(linalg_cast(l)); + } + + template inline + typename part_return::return_type + imag_part(const L &l) { + return typename part_return::return_type + (linalg_cast(const_cast(l))); + } + + template inline + typename part_return::return_type + imag_part(L &l) { + return typename part_return::return_type(linalg_cast(l)); + } + + template struct linalg_traits > { typedef part_vector this_type; @@ -323,47 +479,6 @@ namespace gmm { { return reference(linalg_traits::access(o, it.it, ite.it,i)); } }; - template std::ostream &operator << - (std::ostream &o, const part_vector& m) - { gmm::write(o,m); return o; } - - - /* ********************************************************************* */ - /* Reference to the real or imaginary part of (complex) matrices */ - /* ********************************************************************* */ - - - template struct part_row_ref { - - typedef part_row_ref this_type; - typedef typename std::iterator_traits::value_type M; - typedef M * CPT; - typedef typename std::iterator_traits::reference ref_M; - typedef typename select_ref - ::const_row_iterator, typename linalg_traits - ::row_iterator, PT>::ref_type iterator; - typedef typename linalg_traits::value_type value_type; - typedef typename linalg_traits::reference reference; - typedef typename linalg_traits::porigin_type porigin_type; - - iterator begin_, end_; - porigin_type origin; - size_type nr, nc; - - part_row_ref(ref_M m) - : begin_(mat_row_begin(m)), end_(mat_row_end(m)), - origin(linalg_origin(m)), nr(mat_nrows(m)), nc(mat_ncols(m)) {} - - part_row_ref(const part_row_ref &cr) : - begin_(cr.begin_),end_(cr.end_), origin(cr.origin),nr(cr.nr),nc(cr.nc) {} - - reference operator()(size_type i, size_type j) const { - return reference(ref_or_value_type::r( - linalg_traits::access(begin_+i, j), - PART(), value_type())); - } - }; - template struct linalg_traits > { typedef part_row_ref this_type; @@ -380,9 +495,9 @@ namespace gmm { typedef abstract_null_type const_sub_col_type; typedef abstract_null_type col_iterator; typedef abstract_null_type const_col_iterator; - typedef typename linalg_traits::const_sub_row_type + typedef typename org_type::const_sub_row_type>::t pre_const_sub_row_type; - typedef typename linalg_traits::sub_row_type pre_sub_row_type; + typedef typename org_type::sub_row_type>::t pre_sub_row_type; typedef part_vector const_sub_row_type; typedef typename select_ref - void linalg_traits >::do_clear(this_type &v) { - row_iterator it = mat_row_begin(v), ite = mat_row_end(v); - for (; it != ite; ++it) clear(row(it)); - } - - template std::ostream &operator << - (std::ostream &o, const part_row_ref& m) - { gmm::write(o,m); return o; } - - template struct part_col_ref { - - typedef part_col_ref this_type; - typedef typename std::iterator_traits::value_type M; - typedef M * CPT; - typedef typename std::iterator_traits::reference ref_M; - typedef typename select_ref - ::const_col_iterator, typename linalg_traits - ::col_iterator, PT>::ref_type iterator; - typedef typename linalg_traits::value_type value_type; - typedef typename linalg_traits::reference reference; - typedef typename linalg_traits::porigin_type porigin_type; - - iterator begin_, end_; - porigin_type origin; - size_type nr, nc; - - part_col_ref(ref_M m) - : begin_(mat_col_begin(m)), end_(mat_col_end(m)), - origin(linalg_origin(m)), nr(mat_nrows(m)), nc(mat_ncols(m)) {} - - part_col_ref(const part_col_ref &cr) : - begin_(cr.begin_),end_(cr.end_), origin(cr.origin),nr(cr.nr),nc(cr.nc) {} - - reference operator()(size_type i, size_type j) const { - return reference(ref_or_value_type::r( - linalg_traits::access(begin_+j, i), - PART(), value_type())); - } - }; template struct linalg_traits > { @@ -476,9 +550,9 @@ namespace gmm { typedef abstract_null_type const_sub_row_type; typedef abstract_null_type row_iterator; typedef abstract_null_type const_row_iterator; - typedef typename linalg_traits::const_sub_col_type + typedef typename org_type::const_sub_col_type>::t pre_const_sub_col_type; - typedef typename linalg_traits::sub_col_type pre_sub_col_type; + typedef typename org_type::sub_col_type>::t pre_sub_col_type; typedef part_vector const_sub_col_type; typedef typename select_ref void linalg_traits >::do_clear(this_type &v) { col_iterator it = mat_col_begin(v), ite = mat_col_end(v); for (; it != ite; ++it) clear(col(it)); } - template std::ostream &operator << - (std::ostream &o, const part_col_ref& m) - { gmm::write(o,m); return o; } - - - - - - -template - struct part_return_ { - typedef abstract_null_type return_type; - }; - template - struct part_return_ { - typedef typename std::iterator_traits::value_type L; - typedef typename select_return, - part_row_ref< L *, PART>, PT>::return_type return_type; - }; - template - struct part_return_ { - typedef typename std::iterator_traits::value_type L; - typedef typename select_return, - part_col_ref, PT>::return_type return_type; - }; - - template struct part_return__{ - typedef abstract_null_type return_type; - }; - - template - struct part_return__ { - typedef typename std::iterator_traits::value_type L; - typedef typename part_return_::sub_orientation>::potype, PART, - PT>::return_type return_type; - }; - - template - struct part_return__ { - typedef typename std::iterator_traits::value_type L; - typedef typename select_return, - part_vector, PT>::return_type return_type; - }; - - template struct part_return { - typedef typename std::iterator_traits::value_type L; - typedef typename part_return__::linalg_type>::return_type return_type; - }; - - template inline - typename part_return::return_type - real_part(const L &l) { - return typename part_return::return_type - (linalg_cast(const_cast(l))); - } - - template inline - typename part_return::return_type - real_part(L &l) { - return typename part_return::return_type(linalg_cast(l)); - } - - template inline - typename part_return::return_type - imag_part(const L &l) { - return typename part_return::return_type - (linalg_cast(const_cast(l))); - } - - template inline - typename part_return::return_type - imag_part(L &l) { - return typename part_return::return_type(linalg_cast(l)); + template + void linalg_traits >::do_clear(this_type &v) { + row_iterator it = mat_row_begin(v), ite = mat_row_end(v); + for (; it != ite; ++it) clear(row(it)); } - - - } #endif // GMM_REAL_PART_H diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_ref.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_ref.h similarity index 99% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_ref.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_ref.h index ce17513c8..67af37739 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_ref.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_ref.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2000-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2000-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_scaled.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_scaled.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_scaled.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_scaled.h index ff05094cc..485af32a1 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_scaled.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_scaled.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_scaled.h @@ -110,29 +110,6 @@ namespace gmm { { return value_type(r) * linalg_traits::access(origin, begin_, end_, i); } }; - template struct linalg_traits > { - typedef scaled_vector_const_ref this_type; - typedef linalg_const is_reference; - typedef abstract_vector linalg_type; - typedef typename strongest_numeric_type::value_type>::T value_type; - typedef typename linalg_traits::origin_type origin_type; - typedef value_type reference; - typedef abstract_null_type iterator; - typedef scaled_const_iterator::const_iterator, S> - const_iterator; - typedef typename linalg_traits::storage_type storage_type; - typedef typename linalg_traits::index_sorted index_sorted; - static size_type size(const this_type &v) { return v.size_; } - static const_iterator begin(const this_type &v) - { return const_iterator(v.begin_, v.r); } - static const_iterator end(const this_type &v) - { return const_iterator(v.end_, v.r); } - static const origin_type* origin(const this_type &v) { return v.origin; } - static value_type access(const origin_type *o, const const_iterator &it, - const const_iterator &ite, size_type i) - { return it.r * (linalg_traits::access(o, it.it, ite.it, i)); } - - }; template std::ostream &operator << (std::ostream &o, const scaled_vector_const_ref& m) @@ -197,39 +174,6 @@ namespace gmm { { return r * linalg_traits::access(begin_+i, j); } }; - template struct linalg_traits > { - typedef scaled_row_matrix_const_ref this_type; - typedef linalg_const is_reference; - typedef abstract_matrix linalg_type; - typedef typename linalg_traits::origin_type origin_type; - typedef typename strongest_numeric_type::value_type>::T value_type; - typedef value_type reference; - typedef typename linalg_traits::storage_type storage_type; - typedef typename linalg_traits::const_sub_row_type vector_type; - typedef scaled_vector_const_ref sub_row_type; - typedef scaled_vector_const_ref const_sub_row_type; - typedef scaled_row_const_iterator row_iterator; - typedef scaled_row_const_iterator const_row_iterator; - typedef abstract_null_type const_sub_col_type; - typedef abstract_null_type sub_col_type; - typedef abstract_null_type const_col_iterator; - typedef abstract_null_type col_iterator; - typedef row_major sub_orientation; - typedef typename linalg_traits::index_sorted index_sorted; - static size_type nrows(const this_type &m) - { return m.nr; } - static size_type ncols(const this_type &m) - { return m.nc; } - static const_sub_row_type row(const const_row_iterator &it) - { return scaled(linalg_traits::row(it.it), it.r); } - static const_row_iterator row_begin(const this_type &m) - { return const_row_iterator(m.begin_, m.r); } - static const_row_iterator row_end(const this_type &m) - { return const_row_iterator(m.end_, m.r); } - static const origin_type* origin(const this_type &m) { return m.origin; } - static value_type access(const const_row_iterator &it, size_type i) - { return it.r * (linalg_traits::access(it.it, i)); } - }; template std::ostream &operator << (std::ostream &o, const scaled_row_matrix_const_ref& m) @@ -291,39 +235,7 @@ namespace gmm { { return r * linalg_traits::access(begin_+j, i); } }; - template struct linalg_traits > { - typedef scaled_col_matrix_const_ref this_type; - typedef linalg_const is_reference; - typedef abstract_matrix linalg_type; - typedef typename strongest_numeric_type::value_type>::T value_type; - typedef typename linalg_traits::origin_type origin_type; - typedef value_type reference; - typedef typename linalg_traits::storage_type storage_type; - typedef typename linalg_traits::const_sub_col_type vector_type; - typedef abstract_null_type sub_col_type; - typedef scaled_vector_const_ref const_sub_col_type; - typedef abstract_null_type col_iterator; - typedef scaled_col_const_iterator const_col_iterator; - typedef abstract_null_type const_sub_row_type; - typedef abstract_null_type sub_row_type; - typedef abstract_null_type const_row_iterator; - typedef abstract_null_type row_iterator; - typedef col_major sub_orientation; - typedef typename linalg_traits::index_sorted index_sorted; - static size_type ncols(const this_type &m) - { return m.nc; } - static size_type nrows(const this_type &m) - { return m.nr; } - static const_sub_col_type col(const const_col_iterator &it) - { return scaled(linalg_traits::col(it.it), it.r); } - static const_col_iterator col_begin(const this_type &m) - { return const_col_iterator(m.begin_, m.r); } - static const_col_iterator col_end(const this_type &m) - { return const_col_iterator(m.end_, m.r); } - static const origin_type* origin(const this_type &m) { return m.origin; } - static value_type access(const const_col_iterator &it, size_type i) - { return it.r * (linalg_traits::access(it.it, i)); } - }; + template std::ostream &operator << (std::ostream &o, const scaled_col_matrix_const_ref& m) @@ -384,7 +296,7 @@ namespace gmm { return scaled_col_matrix_const_ref(m, x); } - + /* ******************************************************************** */ /* matrix or vector scale */ /* ******************************************************************** */ @@ -423,6 +335,100 @@ namespace gmm { for ( ; it != ite; ++it) scale(linalg_traits::col(it), a); } + template struct linalg_traits > { + typedef scaled_vector_const_ref this_type; + typedef linalg_const is_reference; + typedef abstract_vector linalg_type; + typedef typename strongest_numeric_type::value_type>::T value_type; + typedef typename linalg_traits::origin_type origin_type; + typedef value_type reference; + typedef abstract_null_type iterator; + typedef scaled_const_iterator::const_iterator, S> + const_iterator; + typedef typename linalg_traits::storage_type storage_type; + typedef typename linalg_traits::index_sorted index_sorted; + static size_type size(const this_type &v) { return v.size_; } + static const_iterator begin(const this_type &v) + { return const_iterator(v.begin_, v.r); } + static const_iterator end(const this_type &v) + { return const_iterator(v.end_, v.r); } + static const origin_type* origin(const this_type &v) { return v.origin; } + static value_type access(const origin_type *o, const const_iterator &it, + const const_iterator &ite, size_type i) + { return it.r * (linalg_traits::access(o, it.it, ite.it, i)); } + + }; + + + template struct linalg_traits > { + typedef scaled_row_matrix_const_ref this_type; + typedef linalg_const is_reference; + typedef abstract_matrix linalg_type; + typedef typename linalg_traits::origin_type origin_type; + typedef typename strongest_numeric_type::value_type>::T value_type; + typedef value_type reference; + typedef typename linalg_traits::storage_type storage_type; + typedef typename org_type::const_sub_row_type>::t vector_type; + typedef scaled_vector_const_ref sub_row_type; + typedef scaled_vector_const_ref const_sub_row_type; + typedef scaled_row_const_iterator row_iterator; + typedef scaled_row_const_iterator const_row_iterator; + typedef abstract_null_type const_sub_col_type; + typedef abstract_null_type sub_col_type; + typedef abstract_null_type const_col_iterator; + typedef abstract_null_type col_iterator; + typedef row_major sub_orientation; + typedef typename linalg_traits::index_sorted index_sorted; + static size_type nrows(const this_type &m) + { return m.nr; } + static size_type ncols(const this_type &m) + { return m.nc; } + static const_sub_row_type row(const const_row_iterator &it) + { return scaled(linalg_traits::row(it.it), it.r); } + static const_row_iterator row_begin(const this_type &m) + { return const_row_iterator(m.begin_, m.r); } + static const_row_iterator row_end(const this_type &m) + { return const_row_iterator(m.end_, m.r); } + static const origin_type* origin(const this_type &m) { return m.origin; } + static value_type access(const const_row_iterator &it, size_type i) + { return it.r * (linalg_traits::access(it.it, i)); } + }; + + template struct linalg_traits > { + typedef scaled_col_matrix_const_ref this_type; + typedef linalg_const is_reference; + typedef abstract_matrix linalg_type; + typedef typename strongest_numeric_type::value_type>::T value_type; + typedef typename linalg_traits::origin_type origin_type; + typedef value_type reference; + typedef typename linalg_traits::storage_type storage_type; + typedef typename org_type::const_sub_col_type>::t vector_type; + typedef abstract_null_type sub_col_type; + typedef scaled_vector_const_ref const_sub_col_type; + typedef abstract_null_type col_iterator; + typedef scaled_col_const_iterator const_col_iterator; + typedef abstract_null_type const_sub_row_type; + typedef abstract_null_type sub_row_type; + typedef abstract_null_type const_row_iterator; + typedef abstract_null_type row_iterator; + typedef col_major sub_orientation; + typedef typename linalg_traits::index_sorted index_sorted; + static size_type ncols(const this_type &m) + { return m.nc; } + static size_type nrows(const this_type &m) + { return m.nr; } + static const_sub_col_type col(const const_col_iterator &it) + { return scaled(linalg_traits::col(it.it), it.r); } + static const_col_iterator col_begin(const this_type &m) + { return const_col_iterator(m.begin_, m.r); } + static const_col_iterator col_end(const this_type &m) + { return const_col_iterator(m.end_, m.r); } + static const origin_type* origin(const this_type &m) { return m.origin; } + static value_type access(const const_col_iterator &it, size_type i) + { return it.r * (linalg_traits::access(it.it, i)); } + }; + + } #endif // GMM_SCALED_H__ diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_Schwarz_additive.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_Schwarz_additive.h similarity index 99% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_Schwarz_additive.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_Schwarz_additive.h index a842f497f..7f8554b5a 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_Schwarz_additive.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_Schwarz_additive.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_solver_Schwarz_additive.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_bfgs.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_bfgs.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_bfgs.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_bfgs.h index 7d34c5239..28a1bc01f 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_bfgs.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_bfgs.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2004-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2004-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_solver_bfgs.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_bicgstab.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_bicgstab.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_bicgstab.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_bicgstab.h index 5a176fe01..858478fbe 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_bicgstab.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_bicgstab.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ // This file is a modified version of bicgstab.h from ITL. diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_cg.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_cg.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_cg.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_cg.h index 8c34bb249..a2876786a 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_cg.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_cg.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ // This file is a modified version of cg.h from ITL. diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_constrained_cg.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_constrained_cg.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_constrained_cg.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_constrained_cg.h index a9463cf13..44716bffe 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_constrained_cg.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_constrained_cg.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_solver_constrained_cg.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_gmres.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_gmres.h similarity index 97% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_gmres.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_gmres.h index 006dad41e..b124905e2 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_gmres.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_gmres.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ // This file is a modified version of gmres.h from ITL. diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_idgmres.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_idgmres.h similarity index 99% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_idgmres.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_idgmres.h index 140da877c..79bb9064d 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_idgmres.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_idgmres.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard, Caroline Lecalvez - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard, Caroline Lecalvez + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_solver_idgmres.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_qmr.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_qmr.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_qmr.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_qmr.h index 8aaea6813..ca6b8e075 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_solver_qmr.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_solver_qmr.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ // This file is a modified version of qmr.h from ITL. diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_std.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_std.h similarity index 80% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_std.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_std.h index b496b6925..2e128dd0f 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_std.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_std.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_std.h @@ -38,6 +38,8 @@ #ifndef GMM_STD_H__ #define GMM_STD_H__ +// #include + #ifndef __USE_STD_IOSTREAM # define __USE_STD_IOSTREAM #endif @@ -74,7 +76,8 @@ # define SECURE_STRDUP(s) strdup(s) #endif -#define GMM_NOPERATION(a) { abs(&(a) != &(a)); } +inline void GMM_NOPERATION_(int) { } +#define GMM_NOPERATION(a) { GMM_NOPERATION_(abs(&(a) != &(a))); } /* ********************************************************************** */ /* Compilers detection. */ @@ -85,7 +88,7 @@ # include # undef _RWSTD_NO_CLASS_PARTIAL_SPEC # undef _RWSTD_NO_NAMESPACE -#endif +#endif */ /* for VISUAL C++ ... #if defined(_MSC_VER) // && !defined(__MWERKS__) @@ -94,8 +97,8 @@ */ #if defined(__GNUC__) -# if (__GNUC__ < 3) -# error : PLEASE UPDATE g++ TO AT LEAST 3.0 VERSION +# if (__GNUC__ < 4) +# error : PLEASE UPDATE g++ TO AT LEAST 4.8 VERSION # endif #endif @@ -111,7 +114,7 @@ #include #include #include -//#include +//#include #include #include #include @@ -126,10 +129,60 @@ #include #include #include +#include +#include #include +namespace std { +#if defined(__GNUC__) && (__cplusplus <= 201103L) + template + struct _MakeUniq + { typedef unique_ptr<_Tp> __single_object; }; + template + struct _MakeUniq<_Tp[]> + { typedef unique_ptr<_Tp[]> __array; }; + template + struct _MakeUniq<_Tp[_Bound]> + { struct __invalid_type { }; }; + /// std::make_unique for single objects + template + inline typename _MakeUniq<_Tp>::__single_object + make_unique(_Args&&... __args) + { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } + /// std::make_unique for arrays of unknown bound + template + inline typename _MakeUniq<_Tp>::__array + make_unique(size_t __num) + { return unique_ptr<_Tp>(new typename remove_extent<_Tp>::type[__num]()); } + /// Disable std::make_unique for arrays of known bound + template + inline typename _MakeUniq<_Tp>::__invalid_type + make_unique(_Args&&...) = delete; +#endif + + + // Should simply be replaced by std::shared_ptr when it will be supported + // by the STL + template class shared_array_ptr : shared_ptr { + public: + shared_array_ptr() {} + shared_array_ptr(T *q) : std::shared_ptr(q, default_delete()) {} + template shared_array_ptr(const std::shared_ptr &p, T *q) + : std::shared_ptr(p, q) {} + T *get() const { return shared_ptr::get(); } + T& operator*() const { return shared_ptr::operator*(); } + T* operator->() const { return shared_ptr::operator->(); } + }; + + template shared_array_ptr make_shared_array(size_t num) + { return shared_array_ptr(new T[num]); } +} + + + + +#ifdef GETFEM_HAVE_OPENMP -#ifdef GETFEM_HAVE_OPENMP #include /**number of OpenMP threads*/ inline size_t num_threads(){return omp_get_max_threads();} @@ -146,7 +199,7 @@ namespace gmm { using std::endl; using std::cout; using std::cerr; - using std::ends; using std::cin; + using std::ends; using std::cin; using std::isnan; #ifdef _WIN32 @@ -156,16 +209,16 @@ namespace gmm { public : inline standard_locale(void) : cinloc(cin.getloc()) { - if (!me_is_multithreaded_now()){ + if (!me_is_multithreaded_now()){ cloc=setlocale(LC_NUMERIC, 0); - setlocale(LC_NUMERIC,"C"); + setlocale(LC_NUMERIC,"C"); } } inline ~standard_locale() { - if (!me_is_multithreaded_now()) - setlocale(LC_NUMERIC, cloc.c_str()); - + if (!me_is_multithreaded_now()) + setlocale(LC_NUMERIC, cloc.c_str()); + } }; #else @@ -176,7 +229,7 @@ namespace gmm { //public : // inline standard_locale(void) : oldloc(uselocale((locale_t)0)) - // { + // { // temploc = newlocale(LC_NUMERIC, "C", NULL); // uselocale(temploc); // } @@ -192,7 +245,7 @@ namespace gmm { class standard_locale { std::string cloc; std::locale cinloc; - + public : inline standard_locale(void) : cloc(setlocale(LC_NUMERIC, 0)), cinloc(cin.getloc()) @@ -207,20 +260,20 @@ namespace gmm { class stream_standard_locale { std::locale cloc; std::ios &io; - + public : inline stream_standard_locale(std::ios &i) : cloc(i.getloc()), io(i) { io.imbue(std::locale("C")); } inline ~stream_standard_locale() { io.imbue(cloc); } }; - - - - + + + + /* ******************************************************************* */ /* Clock functions. */ /* ******************************************************************* */ - + # if defined(HAVE_SYS_TIMES) inline double uclock_sec(void) { static double ttclk = 0.; @@ -231,23 +284,23 @@ namespace gmm { inline double uclock_sec(void) { return double(clock())/double(CLOCKS_PER_SEC); } # endif - + /* ******************************************************************** */ /* Fixed size integer types. */ /* ******************************************************************** */ - // Remark : the test program dynamic_array tests the lenght of + // Remark : the test program dynamic_array tests the length of // resulting integers - + template struct fixed_size_integer_generator { typedef void int_base_type; - typedef void uint_base_type; + typedef void uint_base_type; }; - + template <> struct fixed_size_integer_generator { typedef signed char int_base_type; typedef unsigned char uint_base_type; }; - + template <> struct fixed_size_integer_generator { typedef signed short int int_base_type; @@ -318,13 +371,13 @@ typedef fixed_size_integer_generator<8>::uint_base_type uint64_type; // #endif #if defined(__GNUC__) && !defined(__ICC) -/* - g++ can issue a warning at each usage of a function declared with this special attribute +/* + g++ can issue a warning at each usage of a function declared with this special attribute (also works with typedefs and variable declarations) */ # define IS_DEPRECATED __attribute__ ((__deprecated__)) /* - the specified function is inlined at any optimization level + the specified function is inlined at any optimization level */ # define ALWAYS_INLINE __attribute__((always_inline)) #else @@ -339,7 +392,7 @@ typedef fixed_size_integer_generator<8>::uint_base_type uint64_type; /* ******************************************************************** */ #if defined(EXPORTED_TO_SHARED_LIB) -# if defined(_MSC_VER) || defined(__INTEL_COMPILER) +# if defined(_MSC_VER) || defined(__INTEL_COMPILER) # define APIDECL __declspec(dllexport) # elif defined(__GNUC__) # define __attribute__((visibility("default"))) @@ -352,7 +405,7 @@ typedef fixed_size_integer_generator<8>::uint_base_type uint64_type; #endif #if defined(IMPORTED_FROM_SHARED_LIB) -# if defined(_MSC_VER) || defined(__INTEL_COMPILER) +# if defined(_MSC_VER) || defined(__INTEL_COMPILER) # define APIDECL __declspec(dllimport) # else # define APIDECL @@ -369,4 +422,3 @@ typedef fixed_size_integer_generator<8>::uint_base_type uint64_type; #endif #endif /* GMM_STD_H__ */ - diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_sub_index.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_sub_index.h similarity index 98% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_sub_index.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_sub_index.h index a35fe580c..f1f0097ce 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_sub_index.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_sub_index.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_sub_index.h diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_sub_matrix.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_sub_matrix.h similarity index 96% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_sub_matrix.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_sub_matrix.h index 930e44015..e79883c31 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_sub_matrix.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_sub_matrix.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_sub_matrix.h @@ -143,11 +143,11 @@ namespace gmm { typedef abstract_null_type col_iterator; typedef abstract_null_type const_sub_col_type; typedef abstract_null_type const_col_iterator; - typedef typename sub_vector_type::const_sub_row_type *, SUBI2>::vector_type + typedef typename sub_vector_type::const_sub_row_type>::t *, SUBI2>::vector_type const_sub_row_type; typedef typename select_ref::sub_row_type *, + typename sub_vector_type::sub_row_type>::t *, SUBI2>::vector_type, PT>::ref_type sub_row_type; typedef gen_sub_row_matrix_iterator::pointer, SUBI1, SUBI2> const_row_iterator; @@ -290,12 +290,8 @@ namespace gmm { typedef abstract_null_type row_iterator; typedef abstract_null_type const_sub_row_type; typedef abstract_null_type const_row_iterator; - typedef typename sub_vector_type::const_sub_col_type *, SUBI1>::vector_type - const_sub_col_type; - typedef typename select_ref::sub_col_type *, - SUBI1>::vector_type, PT>::ref_type sub_col_type; + typedef typename sub_vector_type::const_sub_col_type>::t *, SUBI1>::vector_type const_sub_col_type; + typedef typename select_ref::sub_col_type>::t *, SUBI1>::vector_type, PT>::ref_type sub_col_type; typedef gen_sub_col_matrix_iterator::pointer, SUBI1, SUBI2> const_col_iterator; typedef typename select_ref::const_sub_row_type const_sub_col_type; typedef typename select_ref::sub_row_type, PT>::ref_type sub_col_type; + linalg_traits::sub_row_type, PT>::ref_type sub_col_type; typedef typename linalg_traits::const_row_iterator const_col_iterator; typedef typename select_ref::row_iterator, PT>::ref_type col_iterator; @@ -171,7 +171,7 @@ namespace gmm { typedef abstract_null_type const_col_iterator; typedef typename linalg_traits::const_sub_col_type const_sub_row_type; typedef typename select_ref::sub_col_type, PT>::ref_type sub_row_type; + linalg_traits::sub_col_type, PT>::ref_type sub_row_type; typedef typename linalg_traits::const_col_iterator const_row_iterator; typedef typename select_ref::col_iterator, PT>::ref_type row_iterator; diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_tri_solve.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_tri_solve.h similarity index 87% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_tri_solve.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_tri_solve.h index 583b83ec8..d05520eb3 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_tri_solve.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_tri_solve.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_tri_solve.h @@ -44,12 +44,12 @@ namespace gmm { template void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k, - col_major, abstract_sparse, bool is_unit) { + col_major, abstract_sparse, bool is_unit) { typename linalg_traits::value_type x_j; for (int j = int(k) - 1; j >= 0; --j) { typedef typename linalg_traits::const_sub_col_type COL; COL c = mat_const_col(T, j); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(c), ite = vect_const_end(c); if (!is_unit) x[j] /= c[j]; for (x_j = x[j]; it != ite ; ++it) @@ -59,12 +59,12 @@ namespace gmm { template void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k, - col_major, abstract_dense, bool is_unit) { + col_major, abstract_dense, bool is_unit) { typename linalg_traits::value_type x_j; for (int j = int(k) - 1; j >= 0; --j) { typedef typename linalg_traits::const_sub_col_type COL; COL c = mat_const_col(T, j); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(c), ite = it + j; typename linalg_traits::iterator itx = vect_begin(x); if (!is_unit) x[j] /= c[j]; @@ -74,14 +74,14 @@ namespace gmm { template void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k, - col_major, abstract_sparse, bool is_unit) { + col_major, abstract_sparse, bool is_unit) { typename linalg_traits::value_type x_j; // cout << "(lower col)The Tri Matrix = " << T << endl; // cout << "k = " << endl; for (int j = 0; j < int(k); ++j) { typedef typename linalg_traits::const_sub_col_type COL; COL c = mat_const_col(T, j); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(c), ite = vect_const_end(c); if (!is_unit) x[j] /= c[j]; for (x_j = x[j]; it != ite ; ++it) @@ -91,12 +91,12 @@ namespace gmm { template void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k, - col_major, abstract_dense, bool is_unit) { + col_major, abstract_dense, bool is_unit) { typename linalg_traits::value_type x_j; for (int j = 0; j < int(k); ++j) { typedef typename linalg_traits::const_sub_col_type COL; COL c = mat_const_col(T, j); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(c) + (j+1), ite = vect_const_begin(c) + k; typename linalg_traits::iterator itx = vect_begin(x) + (j+1); if (!is_unit) x[j] /= c[j]; @@ -107,7 +107,7 @@ namespace gmm { template void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k, - row_major, abstract_sparse, bool is_unit) { + row_major, abstract_sparse, bool is_unit) { typedef typename linalg_traits::const_sub_row_type ROW; typename linalg_traits::value_type t; typename linalg_traits::const_row_iterator @@ -115,7 +115,7 @@ namespace gmm { for (int i = int(k) - 1; i >= 0; --i) { --itr; ROW c = linalg_traits::row(itr); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(c), ite = vect_const_end(c); for (t = x[i]; it != ite; ++it) if (int(it.index()) > i && it.index() < k) t -= (*it) * x[it.index()]; @@ -125,13 +125,13 @@ namespace gmm { template void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k, - row_major, abstract_dense, bool is_unit) { + row_major, abstract_dense, bool is_unit) { typename linalg_traits::value_type t; for (int i = int(k) - 1; i >= 0; --i) { typedef typename linalg_traits::const_sub_row_type ROW; ROW c = mat_const_row(T, i); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(c) + (i + 1), ite = vect_const_begin(c) + k; typename linalg_traits::iterator itx = vect_begin(x) + (i+1); @@ -142,13 +142,13 @@ namespace gmm { template void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k, - row_major, abstract_sparse, bool is_unit) { + row_major, abstract_sparse, bool is_unit) { typename linalg_traits::value_type t; for (int i = 0; i < int(k); ++i) { typedef typename linalg_traits::const_sub_row_type ROW; ROW c = mat_const_row(T, i); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(c), ite = vect_const_end(c); for (t = x[i]; it != ite; ++it) @@ -159,13 +159,13 @@ namespace gmm { template void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k, - row_major, abstract_dense, bool is_unit) { + row_major, abstract_dense, bool is_unit) { typename linalg_traits::value_type t; for (int i = 0; i < int(k); ++i) { typedef typename linalg_traits::const_sub_row_type ROW; ROW c = mat_const_row(T, i); - typename linalg_traits::const_iterator + typename linalg_traits::t>::const_iterator it = vect_const_begin(c), ite = it + i; typename linalg_traits::iterator itx = vect_begin(x); diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_vector.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_vector.h similarity index 60% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_vector.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_vector.h index 5d75d3dd4..e69931dbe 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_vector.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_vector.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2002-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2002-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_vector.h @author Yves Renard @@ -58,28 +58,89 @@ namespace gmm { operator T() const { return pm->r(l); } ref_elt_vector(V *p, size_type ll) : pm(p), l(ll) {} - inline ref_elt_vector &operator =(T v) - { (*pm).w(l,v); return *this; } inline bool operator ==(T v) const { return ((*pm).r(l) == v); } inline bool operator !=(T v) const { return ((*pm).r(l) != v); } + inline bool operator ==(std::complex v) const + { return ((*pm).r(l) == v); } + inline bool operator !=(std::complex v) const + { return ((*pm).r(l) != v); } inline ref_elt_vector &operator +=(T v) - { (*pm).w(l,(*pm).r(l) + v); return *this; } + { (*pm).wa(l, v); return *this; } inline ref_elt_vector &operator -=(T v) - { (*pm).w(l,(*pm).r(l) - v); return *this; } + { (*pm).wa(l, -v); return *this; } inline ref_elt_vector &operator /=(T v) - { (*pm).w(l,(*pm).r(l) / v); return *this; } + { (*pm).w(l,(*pm).r(l) / v); return *this; } inline ref_elt_vector &operator *=(T v) - { (*pm).w(l,(*pm).r(l) * v); return *this; } + { (*pm).w(l,(*pm).r(l) * v); return *this; } inline ref_elt_vector &operator =(const ref_elt_vector &re) - { *this = T(re); return *this; } - T operator +() { return T(*this); } // necessary for unknow reason - T operator -() { return -T(*this); } // necessary for unknow reason - T operator +(T v) { return T(*this)+ v; } // necessary for unknow reason - T operator -(T v) { return T(*this)- v; } // necessary for unknow reason - T operator *(T v) { return T(*this)* v; } // necessary for unknow reason - T operator /(T v) { return T(*this)/ v; } // necessary for unknow reason + { *this = T(re); return *this; } + inline ref_elt_vector &operator =(T v) + { (*pm).w(l,v); return *this; } + T operator +() { return T(*this); } + T operator -() { return -T(*this); } + T operator +(T v) { return T(*this)+ v; } + T operator -(T v) { return T(*this)- v; } + T operator *(T v) { return T(*this)* v; } + T operator /(T v) { return T(*this)/ v; } + std::complex operator +(std::complex v) { return T(*this)+ v; } + std::complex operator -(std::complex v) { return T(*this)- v; } + std::complex operator *(std::complex v) { return T(*this)* v; } + std::complex operator /(std::complex v) { return T(*this)/ v; } + }; + + template class ref_elt_vector,V> { + + V *pm; + size_type l; + + public : + + operator std::complex() const { return pm->r(l); } + ref_elt_vector(V *p, size_type ll) : pm(p), l(ll) {} + inline bool operator ==(std::complex v) const + { return ((*pm).r(l) == v); } + inline bool operator !=(std::complex v) const + { return ((*pm).r(l) != v); } + inline bool operator ==(T v) const { return ((*pm).r(l) == v); } + inline bool operator !=(T v) const { return ((*pm).r(l) != v); } + inline ref_elt_vector &operator +=(std::complex v) + { (*pm).w(l,(*pm).r(l) + v); return *this; } + inline ref_elt_vector &operator -=(std::complex v) + { (*pm).w(l,(*pm).r(l) - v); return *this; } + inline ref_elt_vector &operator /=(std::complex v) + { (*pm).w(l,(*pm).r(l) / v); return *this; } + inline ref_elt_vector &operator *=(std::complex v) + { (*pm).w(l,(*pm).r(l) * v); return *this; } + inline ref_elt_vector &operator =(const ref_elt_vector &re) + { *this = T(re); return *this; } + inline ref_elt_vector &operator =(std::complex v) + { (*pm).w(l,v); return *this; } + inline ref_elt_vector &operator =(T v) + { (*pm).w(l,std::complex(v)); return *this; } + inline ref_elt_vector &operator +=(T v) + { (*pm).w(l,(*pm).r(l) + v); return *this; } + inline ref_elt_vector &operator -=(T v) + { (*pm).w(l,(*pm).r(l) - v); return *this; } + inline ref_elt_vector &operator /=(T v) + { (*pm).w(l,(*pm).r(l) / v); return *this; } + inline ref_elt_vector &operator *=(T v) + { (*pm).w(l,(*pm).r(l) * v); return *this; } + std::complex operator +() { return std::complex(*this); } + std::complex operator -() { return -std::complex(*this); } + std::complex operator +(T v) { return std::complex(*this)+ v; } + std::complex operator -(T v) { return std::complex(*this)- v; } + std::complex operator *(T v) { return std::complex(*this)* v; } + std::complex operator /(T v) { return std::complex(*this)/ v; } + std::complex operator +(std::complex v) + { return std::complex(*this)+ v; } + std::complex operator -(std::complex v) + { return std::complex(*this)- v; } + std::complex operator *(std::complex v) + { return std::complex(*this)* v; } + std::complex operator /(std::complex v) + { return std::complex(*this)/ v; } }; - + template inline bool operator ==(T v, const ref_elt_vector &re) { return (v==T(re)); } @@ -98,25 +159,37 @@ namespace gmm { T &operator /=(T &v, const ref_elt_vector &re) { v /= T(re); return v; } template inline - T operator +(const ref_elt_vector &re) { return T(re); } + T operator +(T v, const ref_elt_vector &re) { return v+ T(re); } template inline - T operator -(const ref_elt_vector &re) { return -T(re); } + T operator -(T v, const ref_elt_vector &re) { return v- T(re); } template inline - T operator +(const ref_elt_vector &re, T v) { return T(re)+ v; } + T operator *(T v, const ref_elt_vector &re) { return v* T(re); } template inline - T operator +(T v, const ref_elt_vector &re) { return v+ T(re); } + T operator /(T v, const ref_elt_vector &re) { return v/ T(re); } template inline - T operator -(const ref_elt_vector &re, T v) { return T(re)- v; } + std::complex operator +(std::complex v, const ref_elt_vector &re) + { return v+ T(re); } template inline - T operator -(T v, const ref_elt_vector &re) { return v- T(re); } - template inline - T operator *(const ref_elt_vector &re, T v) { return T(re)* v; } + std::complex operator -(std::complex v, const ref_elt_vector &re) + { return v- T(re); } template inline - T operator *(T v, const ref_elt_vector &re) { return v* T(re); } + std::complex operator *(std::complex v, const ref_elt_vector &re) + { return v* T(re); } template inline - T operator /(const ref_elt_vector &re, T v) { return T(re)/ v; } + std::complex operator /(std::complex v, const ref_elt_vector &re) + { return v/ T(re); } template inline - T operator /(T v, const ref_elt_vector &re) { return v/ T(re); } + std::complex operator +(T v, const ref_elt_vector, V> &re) + { return v+ std::complex(re); } + template inline + std::complex operator -(T v, const ref_elt_vector, V> &re) + { return v- std::complex(re); } + template inline + std::complex operator *(T v, const ref_elt_vector, V> &re) + { return v* std::complex(re); } + template inline + std::complex operator /(T v, const ref_elt_vector, V> &re) + { return v/ std::complex(re); } template inline typename number_traits::magnitude_type abs(const ref_elt_vector &re) { return gmm::abs(T(re)); } @@ -136,11 +209,474 @@ namespace gmm { typename number_traits::magnitude_type imag(const ref_elt_vector &re) { return gmm::imag(T(re)); } + /*************************************************************************/ + /* */ + /* Class dsvector: sparse vector optimized for random write operations */ + /* with constant complexity for read and write operations. */ + /* Based on distribution sort principle. */ + /* Cheap for densely populated vectors. */ + /* */ + /*************************************************************************/ + + template class dsvector; + + template struct dsvector_iterator { + size_type i; // Current index. + T* p; // Pointer to the current position. + dsvector *v; // Pointer to the vector. + + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + // typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef dsvector_iterator iterator; + + reference operator *() const { return *p; } + pointer operator->() const { return &(operator*()); } + + iterator &operator ++() { + for (size_type k = (i & 15); k < 15; ++k) + { ++p; ++i; if (*p != T(0)) return *this; } + v->next_pos(*(const_cast(&(p))), i); + return *this; + } + iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; } + iterator &operator --() { + for (size_type k = (i & 15); k > 0; --k) + { --p; --i; if (*p != T(0)) return *this; } + v->previous_pos(p, i); + return *this; + } + iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; } + + bool operator ==(const iterator &it) const + { return (i == it.i && p == it.p && v == it.v); } + bool operator !=(const iterator &it) const + { return !(it == *this); } + + size_type index(void) const { return i; } + + dsvector_iterator(void) : i(size_type(-1)), p(0), v(0) {} + dsvector_iterator(dsvector &w) : i(size_type(-1)), p(0), v(&w) {}; + }; + + + template struct dsvector_const_iterator { + size_type i; // Current index. + const T* p; // Pointer to the current position. + const dsvector *v; // Pointer to the vector. + + typedef T value_type; + typedef const value_type* pointer; + typedef const value_type& reference; + // typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef dsvector_const_iterator iterator; + + reference operator *() const { return *p; } + pointer operator->() const { return &(operator*()); } + iterator &operator ++() { + for (size_type k = (i & 15); k < 15; ++k) + { ++p; ++i; if (*p != T(0)) return *this; } + v->next_pos(p, i); + return *this; + } + iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; } + iterator &operator --() { + for (size_type k = (i & 15); k > 0; --k) + { --p; --i; if (*p != T(0)) return *this; } + v->previous_pos(p, i); + return *this; + } + iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; } + + bool operator ==(const iterator &it) const + { return (i == it.i && p == it.p && v == it.v); } + bool operator !=(const iterator &it) const + { return !(it == *this); } + + size_type index(void) const { return i; } + + dsvector_const_iterator(void) : i(size_type(-1)), p(0) {} + dsvector_const_iterator(const dsvector_iterator &it) + : i(it.i), p(it.p), v(it.v) {} + dsvector_const_iterator(const dsvector &w) + : i(size_type(-1)), p(0), v(&w) {}; + }; + + /** + Sparse vector built on distribution sort principle. + Read and write access have a constant complexity depending only on the + vector size. + */ + template class dsvector { + + typedef dsvector_iterator iterator; + typedef dsvector_const_iterator const_iterator; + typedef dsvector this_type; + typedef T * pointer; + typedef const T * const_pointer; + typedef void * void_pointer; + typedef const void * const_void_pointer; + + protected: + size_type n; // Potential vector size + size_type depth; // Number of row of pointer arrays + size_type mask; // Mask for the first pointer array + size_type shift; // Shift for the first pointer array + void_pointer root_ptr; // Root pointer + + const T *read_access(size_type i) const { + GMM_ASSERT1(i < n, "index out of range"); + size_type my_mask = mask, my_shift = shift; + void_pointer p = root_ptr; + if (!p) return 0; + for (size_type k = 0; k < depth; ++k) { + p = ((void **)(p))[(i & my_mask) >> my_shift]; + if (!p) return 0; + my_mask = (my_mask >> 4); + my_shift -= 4; + } + GMM_ASSERT1(my_shift == 0, "internal error"); + GMM_ASSERT1(my_mask == 15, "internal error"); + return &(((const T *)(p))[i & 15]); + } + T *write_access(size_type i) { + GMM_ASSERT1(i < n, "index " << i << " out of range (size " << n << ")"); + size_type my_mask = mask, my_shift = shift; + if (!root_ptr) { + if (depth) { + root_ptr = new void_pointer[16]; + std::memset(root_ptr, 0, 16*sizeof(void_pointer)); + } else { + root_ptr = new T[16]; + for (size_type l = 0; l < 16; ++l) ((T *)(root_ptr))[l] = T(0); + } + } + + void_pointer p = root_ptr; + for (size_type k = 0; k < depth; ++k) { + size_type j = (i & my_mask) >> my_shift; + void_pointer q = ((void_pointer *)(p))[j]; + if (!q) { + if (k+1 != depth) { + q = new void_pointer[16]; + std::memset(q, 0, 16*sizeof(void_pointer)); + } else { + q = new T[16]; + for (size_type l = 0; l < 16; ++l) ((T *)(q))[l] = T(0); + } + ((void_pointer *)(p))[j] = q; + } + p = q; + my_mask = (my_mask >> 4); + my_shift -= 4; + } + GMM_ASSERT1(my_shift == 0, "internal error"); + GMM_ASSERT1(my_mask == 15, "internal error " << my_mask); + return &(((T *)(p))[i & 15]); + } + + void init(size_type n_) { + n = n_; depth = 0; shift = 0; mask = 1; if (n_) --n_; + while (n_) { n_ /= 16; ++depth; shift += 4; mask *= 16; } + mask--; if (shift) shift -= 4; if (depth) --depth; + root_ptr = 0; + } + + void rec_del(void_pointer p, size_type my_depth) { + if (my_depth) { + for (size_type k = 0; k < 16; ++k) + if (((void_pointer *)(p))[k]) + rec_del(((void_pointer *)(p))[k], my_depth-1); + delete[] ((void_pointer *)(p)); + } else { + delete[] ((T *)(p)); + } + } + + void rec_clean(void_pointer p, size_type my_depth, double eps) { + if (my_depth) { + for (size_type k = 0; k < 16; ++k) + if (((void_pointer *)(p))[k]) + rec_clean(((void_pointer *)(p))[k], my_depth-1, eps); + } else { + for (size_type k = 0; k < 16; ++k) + if (gmm::abs(((T *)(p))[k]) <= eps) ((T *)(p))[k] = T(0); + } + } + + void rec_clean_i(void_pointer p, size_type my_depth, size_type my_mask, + size_type i, size_type base) { + if (my_depth) { + my_mask = (my_mask >> 4); + for (size_type k = 0; k < 16; ++k) + if (((void_pointer *)(p))[k] && (base + (k+1)*(mask+1)) >= i) + rec_clean_i(((void_pointer *)(p))[k], my_depth-1, my_mask, + i, base + k*(my_mask+1)); + } else { + for (size_type k = 0; k < 16; ++k) + if (base+k > i) ((T *)(p))[k] = T(0); + } + } + + + size_type rec_nnz(void_pointer p, size_type my_depth) const { + size_type nn = 0; + if (my_depth) { + for (size_type k = 0; k < 16; ++k) + if (((void_pointer *)(p))[k]) + nn += rec_nnz(((void_pointer *)(p))[k], my_depth-1); + } else { + for (size_type k = 0; k < 16; ++k) + if (((const T *)(p))[k] != T(0)) nn++; + } + return nn; + } + + void copy_rec(void_pointer &p, const_void_pointer q, size_type my_depth) { + if (my_depth) { + p = new void_pointer[16]; + std::memset(p, 0, 16*sizeof(void_pointer)); + for (size_type l = 0; l < 16; ++l) + if (((const const_void_pointer *)(q))[l]) + copy_rec(((void_pointer *)(p))[l], + ((const const_void_pointer *)(q))[l], my_depth-1); + } else { + p = new T[16]; + for (size_type l = 0; l < 16; ++l) ((T *)(p))[l] = ((const T *)(q))[l]; + } + } + + void copy(const dsvector &v) { + if (root_ptr) rec_del(root_ptr, depth); + root_ptr = 0; + mask = v.mask; depth = v.depth; n = v.n; shift = v.shift; + if (v.root_ptr) copy_rec(root_ptr, v.root_ptr, depth); + } + + void next_pos_rec(void_pointer p, size_type my_depth, size_type my_mask, + const_pointer &pp, size_type &i, size_type base) const { + size_type ii = i; + if (my_depth) { + my_mask = (my_mask >> 4); + for (size_type k = 0; k < 16; ++k) + if (((void_pointer *)(p))[k] && (base + (k+1)*(my_mask+1)) >= i) { + next_pos_rec(((void_pointer *)(p))[k], my_depth-1, my_mask, + pp, i, base + k*(my_mask+1)); + if (i != size_type(-1)) return; else i = ii; + } + i = size_type(-1); pp = 0; + } else { + for (size_type k = 0; k < 16; ++k) + if (base+k > i && ((const_pointer)(p))[k] != T(0)) + { i = base+k; pp = &(((const_pointer)(p))[k]); return; } + i = size_type(-1); pp = 0; + } + } + + void previous_pos_rec(void_pointer p, size_type my_depth, size_type my_mask, + const_pointer &pp, size_type &i, + size_type base) const { + size_type ii = i; + if (my_depth) { + my_mask = (my_mask >> 4); + for (size_type k = 15; k != size_type(-1); --k) + if (((void_pointer *)(p))[k] && ((base + k*(my_mask+1)) < i)) { + previous_pos_rec(((void_pointer *)(p))[k], my_depth-1, + my_mask, pp, i, base + k*(my_mask+1)); + if (i != size_type(-1)) return; else i = ii; + } + i = size_type(-1); pp = 0; + } else { + for (size_type k = 15; k != size_type(-1); --k) + if (base+k < i && ((const_pointer)(p))[k] != T(0)) + { i = base+k; pp = &(((const_pointer)(p))[k]); return; } + i = size_type(-1); pp = 0; + } + } + + + public: + void clean(double eps) { if (root_ptr) rec_clean(root_ptr, depth); } + void resize(size_type n_) { + if (n_ != n) { + n = n_; + if (n_ < n) { // Depth unchanged (a choice) + if (root_ptr) rec_clean_i(root_ptr, depth, mask, n_, 0); + } else { + // may change the depth (add some levels) + size_type my_depth = 0, my_shift = 0, my_mask = 1; if (n_) --n_; + while (n_) { n_ /= 16; ++my_depth; my_shift += 4; my_mask *= 16; } + my_mask--; if (my_shift) my_shift -= 4; if (my_depth) --my_depth; + if (my_depth > depth || depth == 0) { + if (root_ptr) { + for (size_type k = depth; k < my_depth; ++k) { + void_pointer *q = new void_pointer [16]; + std::memset(q, 0, 16*sizeof(void_pointer)); + q[0] = root_ptr; root_ptr = q; + } + } + mask = my_mask; depth = my_depth; shift = my_shift; + } + } + } + } + + void clear(void) { if (root_ptr) rec_del(root_ptr, depth); root_ptr = 0; } + + void next_pos(const_pointer &pp, size_type &i) const { + if (!root_ptr || i >= n) { pp = 0, i = size_type(-1); return; } + next_pos_rec(root_ptr, depth, mask, pp, i, 0); + } + + void previous_pos(const_pointer &pp, size_type &i) const { + if (!root_ptr) { pp = 0, i = size_type(-1); return; } + if (i == size_type(-1)) { i = n; } + previous_pos_rec(root_ptr, depth, mask, pp, i, 0); + } + + iterator begin(void) { + iterator it(*this); + if (n && root_ptr) { + it.i = 0; it.p = const_cast(read_access(0)); + if (!(it.p) || *(it.p) == T(0)) + next_pos(*(const_cast(&(it.p))), it.i); + } + return it; + } + + iterator end(void) { return iterator(*this); } + + const_iterator begin(void) const { + const_iterator it(*this); + if (n && root_ptr) { + it.i = 0; it.p = read_access(0); + if (!(it.p) || *(it.p) == T(0)) next_pos(it.p, it.i); + } + return it; + } + + const_iterator end(void) const { return const_iterator(*this); } + + inline ref_elt_vector > operator [](size_type c) + { return ref_elt_vector >(this, c); } + + inline void w(size_type c, const T &e) { + if (e == T(0)) { if (read_access(c)) *(write_access(c)) = e; } + else *(write_access(c)) = e; + } + + inline void wa(size_type c, const T &e) + { if (e != T(0)) { *(write_access(c)) += e; } } + + inline T r(size_type c) const + { const T *p = read_access(c); if (p) return *p; else return T(0); } + + inline T operator [](size_type c) const { return r(c); } + + size_type nnz(void) const + { if (root_ptr) return rec_nnz(root_ptr, depth); else return 0; } + size_type size(void) const { return n; } + + void swap(dsvector &v) { + std::swap(n, v.n); std::swap(root_ptr, v.root_ptr); + std::swap(depth, v.depth); std::swap(shift, v.shift); + std::swap(mask, v.mask); + } + + /* Constructors */ + dsvector(const dsvector &v) { init(0); copy(v); } + dsvector &operator =(const dsvector &v) { copy(v); return *this; } + explicit dsvector(size_type l){ init(l); } + dsvector(void) { init(0); } + ~dsvector() { if (root_ptr) rec_del(root_ptr, depth); root_ptr = 0; } + }; + + template struct linalg_traits> { + typedef dsvector this_type; + typedef this_type origin_type; + typedef linalg_false is_reference; + typedef abstract_vector linalg_type; + typedef T value_type; + typedef ref_elt_vector > reference; + typedef dsvector_iterator iterator; + typedef dsvector_const_iterator const_iterator; + typedef abstract_sparse storage_type; + typedef linalg_true index_sorted; + static size_type size(const this_type &v) { return v.size(); } + static iterator begin(this_type &v) { return v.begin(); } + static const_iterator begin(const this_type &v) { return v.begin(); } + static iterator end(this_type &v) { return v.end(); } + static const_iterator end(const this_type &v) { return v.end(); } + static origin_type* origin(this_type &v) { return &v; } + static const origin_type* origin(const this_type &v) { return &v; } + static void clear(origin_type* o, const iterator &, const iterator &) + { o->clear(); } + static void do_clear(this_type &v) { v.clear(); } + static value_type access(const origin_type *o, const const_iterator &, + const const_iterator &, size_type i) + { return (*o)[i]; } + static reference access(origin_type *o, const iterator &, const iterator &, + size_type i) + { return (*o)[i]; } + static void resize(this_type &v, size_type n) { v.resize(n); } + }; + + template std::ostream &operator << + (std::ostream &o, const dsvector& v) { gmm::write(o,v); return o; } + + /******* Optimized operations for dsvector ****************************/ + + template inline void copy(const dsvector &v1, + dsvector &v2) { + GMM_ASSERT2(v1.size() == v2.size(), "dimensions mismatch"); + v2 = v1; + } + template inline void copy(const dsvector &v1, + const dsvector &v2) { + GMM_ASSERT2(v1.size() == v2.size(), "dimensions mismatch"); + v2 = const_cast &>(v1); + } + template inline + void copy(const dsvector &v1, const simple_vector_ref *> &v2){ + simple_vector_ref *> + *svr = const_cast *> *>(&v2); + dsvector + *pv = const_cast *>((v2.origin)); + GMM_ASSERT2(vect_size(v1) == vect_size(v2), "dimensions mismatch"); + *pv = v1; svr->begin_ = vect_begin(*pv); svr->end_ = vect_end(*pv); + } + template inline + void copy(const simple_vector_ref *> &v1, + dsvector &v2) + { copy(*(v1.origin), v2); } + template inline + void copy(const simple_vector_ref *> &v1, dsvector &v2) + { copy(*(v1.origin), v2); } + template inline + void copy(const simple_vector_ref *> &v1, + const simple_vector_ref *> &v2) + { copy(*(v1.origin), v2); } + template inline + void copy(const simple_vector_ref *> &v1, + const simple_vector_ref *> &v2) + { copy(*(v1.origin), v2); } + + template + inline size_type nnz(const dsvector& l) { return l.nnz(); } + /*************************************************************************/ /* */ - /* Class wsvector: sparse vector optimized for random write operations. */ + /* Class wsvector: sparse vector optimized for random write operations, */ + /* with log(n) complexity for read and write operations. */ + /* Based on std::map */ /* */ /*************************************************************************/ @@ -211,6 +747,15 @@ namespace gmm { else base_type::operator [](c) = e; } + inline void wa(size_type c, const T &e) { + GMM_ASSERT2(c < nbl, "out of range"); + if (e != T(0)) { + iterator it = this->lower_bound(c); + if (it != this->end() && it->first == c) it->second += e; + else base_type::operator [](c) = e; + } + } + inline T r(size_type c) const { GMM_ASSERT2(c < nbl, "out of range"); const_iterator it = this->lower_bound(c); @@ -227,7 +772,7 @@ namespace gmm { { std::swap(nbl, v.nbl); std::map::swap(v); } - /* Constructeurs */ + /* Constructors */ void init(size_type l) { nbl = l; this->clear(); } explicit wsvector(size_type l){ init(l); } wsvector(void) { init(0); } @@ -334,7 +879,7 @@ namespace gmm { template struct elt_rsvector_ { size_type c; T e; - /* e is initialized by default to avoid some false warnings of valgrind.. + /* e is initialized by default to avoid some false warnings of valgrind. (from http://valgrind.org/docs/manual/mc-manual.html: When memory is read into the CPU's floating point registers, the @@ -436,6 +981,7 @@ namespace gmm { { return ref_elt_vector >(this, c); } void w(size_type c, const T &e); + void wa(size_type c, const T &e); T r(size_type c) const; void swap_indices(size_type i, size_type j); @@ -488,7 +1034,7 @@ namespace gmm { iterator it = std::lower_bound(this->begin(), this->end(), ev); if (it != this->end() && it->c == j) { for (iterator ite = this->end() - 1; it != ite; ++it) *it = *(it+1); - base_type_::resize(nb_stored()-1); + base_resize(nb_stored()-1); } } } @@ -507,21 +1053,48 @@ namespace gmm { else { elt_rsvector_ ev(c, e); if (nb_stored() == 0) { - base_type_::resize(1,ev); + base_type_::push_back(ev); } else { iterator it = std::lower_bound(this->begin(), this->end(), ev); if (it != this->end() && it->c == c) it->e = e; else { - size_type ind = it - this->begin(); - if (this->nb_stored() - ind > 800) + size_type ind = it - this->begin(), nb = this->nb_stored(); + if (nb - ind > 1100) + GMM_WARNING2("Inefficient addition of element in rsvector with " + << this->nb_stored() - ind << " non-zero entries"); + base_type_::push_back(ev); + if (ind != nb) { + it = this->begin() + ind; + iterator ite = this->end(); --ite; iterator itee = ite; + for (; ite != it; --ite) { --itee; *ite = *itee; } + *it = ev; + } + } + } + } + } + + template void rsvector::wa(size_type c, const T &e) { + GMM_ASSERT2(c < nbl, "out of range"); + if (e != T(0)) { + elt_rsvector_ ev(c, e); + if (nb_stored() == 0) { + base_type_::push_back(ev); + } + else { + iterator it = std::lower_bound(this->begin(), this->end(), ev); + if (it != this->end() && it->c == c) it->e += e; + else { + size_type ind = it - this->begin(), nb = this->nb_stored(); + if (nb - ind > 1100) GMM_WARNING2("Inefficient addition of element in rsvector with " << this->nb_stored() - ind << " non-zero entries"); - base_type_::resize(nb_stored()+1, ev); - if (ind != this->nb_stored() - 1) { + base_type_::push_back(ev); + if (ind != nb) { it = this->begin() + ind; - for (iterator ite = this->end() - 1; ite != it; --ite) - *ite = *(ite-1); + iterator ite = this->end(); --ite; iterator itee = ite; + for (; ite != it; --ite) { --itee; *ite = *itee; } *it = ev; } } @@ -530,7 +1103,8 @@ namespace gmm { } template T rsvector::r(size_type c) const { - GMM_ASSERT2(c < nbl, "out of range. Index " << c << " for a length of " << nbl); + GMM_ASSERT2(c < nbl, "out of range. Index " << c + << " for a length of " << nbl); if (nb_stored() != 0) { elt_rsvector_ ev(c); const_iterator it = std::lower_bound(this->begin(), this->end(), ev); @@ -867,6 +1441,7 @@ namespace gmm { { return data.end(); } void w(size_type c, const T &e); + void wa(size_type c, const T &e); T r(size_type c) const { GMM_ASSERT2(c < size_, "out of range"); if (c < shift || c >= shift + data.size()) return T(0); @@ -910,11 +1485,35 @@ namespace gmm { shift = c; } else if (c >= shift + s) { - data.resize(c - shift + 1); - std::fill(data.begin() + s, data.end(), T(0)); + data.resize(c - shift + 1, T(0)); + // std::fill(data.begin() + s, data.end(), T(0)); } data[c - shift] = e; } + + template void slvector::wa(size_type c, const T &e) { + GMM_ASSERT2(c < size_, "out of range"); + size_type s = data.size(); + if (!s) { data.resize(1, e); shift = c; return; } + else if (c < shift) { + data.resize(s + shift - c); + typename std::vector::iterator it = data.begin(),it2=data.end()-1; + typename std::vector::iterator it3 = it2 - shift + c; + for (; it3 >= it; --it3, --it2) *it2 = *it3; + std::fill(it, it + shift - c, T(0)); + shift = c; + data[c - shift] = e; + return; + } + else if (c >= shift + s) { + data.resize(c - shift + 1, T(0)); + data[c - shift] = e; + return; + // std::fill(data.begin() + s, data.end(), T(0)); + } + data[c - shift] += e; + } + template struct linalg_traits > { typedef slvector this_type; diff --git a/resources/3rdparty/gmm-5.0/include/gmm/gmm_vector_to_matrix.h b/resources/3rdparty/gmm-5.2/include/gmm/gmm_vector_to_matrix.h similarity index 99% rename from resources/3rdparty/gmm-5.0/include/gmm/gmm_vector_to_matrix.h rename to resources/3rdparty/gmm-5.2/include/gmm/gmm_vector_to_matrix.h index 01813ccc9..83fc0c54f 100644 --- a/resources/3rdparty/gmm-5.0/include/gmm/gmm_vector_to_matrix.h +++ b/resources/3rdparty/gmm-5.2/include/gmm/gmm_vector_to_matrix.h @@ -1,11 +1,11 @@ /* -*- c++ -*- (enables emacs c++ mode) */ /*=========================================================================== - - Copyright (C) 2003-2015 Yves Renard - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2003-2017 Yves Renard + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + As a special exception, you may use this file as it is a part of a free software library without restriction. Specifically, if other files instantiate templates or use macros or inline functions from this file, @@ -26,7 +26,7 @@ to be covered by the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. - + ===========================================================================*/ /**@file gmm_vector_to_matrix.h diff --git a/resources/3rdparty/gmm-5.0/install-sh b/resources/3rdparty/gmm-5.2/install-sh similarity index 100% rename from resources/3rdparty/gmm-5.0/install-sh rename to resources/3rdparty/gmm-5.2/install-sh diff --git a/resources/3rdparty/gmm-5.0/ltmain.sh b/resources/3rdparty/gmm-5.2/ltmain.sh similarity index 100% rename from resources/3rdparty/gmm-5.0/ltmain.sh rename to resources/3rdparty/gmm-5.2/ltmain.sh diff --git a/resources/3rdparty/gmm-5.2/m4/ax_check_cxx_flag.m4 b/resources/3rdparty/gmm-5.2/m4/ax_check_cxx_flag.m4 new file mode 100644 index 000000000..8a288d3a0 --- /dev/null +++ b/resources/3rdparty/gmm-5.2/m4/ax_check_cxx_flag.m4 @@ -0,0 +1,30 @@ +dnl Copyright (C) 2004-2017 Julien Pommier +dnl +dnl This file is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU Lesser General Public License as published +dnl by the Free Software Foundation; either version 3 of the License, or +dnl (at your option) any later version along with the GCC Runtime Library +dnl Exception either version 3.1 or (at your option) any later version. +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +dnl License and GCC Runtime Library Exception for more details. +dnl You should have received a copy of the GNU Lesser General Public License +dnl along with this program; if not, write to the Free Software Foundation, +dnl Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +AC_DEFUN([AC_CHECK_CXX_FLAG], +[AC_MSG_CHECKING([whether ${CXX} accepts $1]) + +echo 'int main(){}' > conftest.c +if test -z "`${CXX} $1 -o conftest conftest.c 2>&1`"; then + $2="${$2} $1" + echo "yes" +else + echo "no" + $3 +fi +dnl echo "$2=${$2}" +rm -f conftest* +]) + diff --git a/resources/3rdparty/gmm-5.0/m4/ax_prefix_config_h.m4 b/resources/3rdparty/gmm-5.2/m4/ax_prefix_config_h.m4 old mode 100755 new mode 100644 similarity index 98% rename from resources/3rdparty/gmm-5.0/m4/ax_prefix_config_h.m4 rename to resources/3rdparty/gmm-5.2/m4/ax_prefix_config_h.m4 index a3773cca9..2c662ef1f --- a/resources/3rdparty/gmm-5.0/m4/ax_prefix_config_h.m4 +++ b/resources/3rdparty/gmm-5.2/m4/ax_prefix_config_h.m4 @@ -79,9 +79,10 @@ dnl #ifndef _testpkg_const dnl #define _testpkg_const const dnl #endif dnl -dnl @version $Id: ax_prefix_config_h.m4 1867 2005-01-27 14:04:04Z pommier $ +dnl @version $Id$ dnl @author Guiodo Draheim -dnl +dnl @License GPLV3 + AC_DEFUN([AX_PREFIX_CONFIG_H],[AC_REQUIRE([AC_CONFIG_HEADER]) AC_CONFIG_COMMANDS([ifelse($1,,$PACKAGE-config.h,$1)],[dnl AS_VAR_PUSHDEF([_OUT],[ac_prefix_conf_OUT])dnl diff --git a/resources/3rdparty/gmm-5.0/m4/libtool.m4 b/resources/3rdparty/gmm-5.2/m4/libtool.m4 similarity index 100% rename from resources/3rdparty/gmm-5.0/m4/libtool.m4 rename to resources/3rdparty/gmm-5.2/m4/libtool.m4 diff --git a/resources/3rdparty/gmm-5.0/m4/ltoptions.m4 b/resources/3rdparty/gmm-5.2/m4/ltoptions.m4 similarity index 100% rename from resources/3rdparty/gmm-5.0/m4/ltoptions.m4 rename to resources/3rdparty/gmm-5.2/m4/ltoptions.m4 diff --git a/resources/3rdparty/gmm-5.0/m4/ltsugar.m4 b/resources/3rdparty/gmm-5.2/m4/ltsugar.m4 similarity index 100% rename from resources/3rdparty/gmm-5.0/m4/ltsugar.m4 rename to resources/3rdparty/gmm-5.2/m4/ltsugar.m4 diff --git a/resources/3rdparty/gmm-5.0/m4/ltversion.m4 b/resources/3rdparty/gmm-5.2/m4/ltversion.m4 similarity index 100% rename from resources/3rdparty/gmm-5.0/m4/ltversion.m4 rename to resources/3rdparty/gmm-5.2/m4/ltversion.m4 diff --git a/resources/3rdparty/gmm-5.0/m4/lt~obsolete.m4 b/resources/3rdparty/gmm-5.2/m4/lt~obsolete.m4 similarity index 100% rename from resources/3rdparty/gmm-5.0/m4/lt~obsolete.m4 rename to resources/3rdparty/gmm-5.2/m4/lt~obsolete.m4 diff --git a/resources/3rdparty/gmm-5.0/missing b/resources/3rdparty/gmm-5.2/missing similarity index 100% rename from resources/3rdparty/gmm-5.0/missing rename to resources/3rdparty/gmm-5.2/missing diff --git a/resources/3rdparty/gmm-5.0/test-driver b/resources/3rdparty/gmm-5.2/test-driver similarity index 100% rename from resources/3rdparty/gmm-5.0/test-driver rename to resources/3rdparty/gmm-5.2/test-driver diff --git a/resources/3rdparty/gmm-5.0/tests/Makefile.am b/resources/3rdparty/gmm-5.2/tests/Makefile.am similarity index 100% rename from resources/3rdparty/gmm-5.0/tests/Makefile.am rename to resources/3rdparty/gmm-5.2/tests/Makefile.am diff --git a/resources/3rdparty/gmm-5.0/tests/Makefile.in b/resources/3rdparty/gmm-5.2/tests/Makefile.in similarity index 100% rename from resources/3rdparty/gmm-5.0/tests/Makefile.in rename to resources/3rdparty/gmm-5.2/tests/Makefile.in diff --git a/resources/3rdparty/gmm-5.0/tests/dummy.cc b/resources/3rdparty/gmm-5.2/tests/dummy.cc similarity index 100% rename from resources/3rdparty/gmm-5.0/tests/dummy.cc rename to resources/3rdparty/gmm-5.2/tests/dummy.cc diff --git a/resources/3rdparty/gmm-5.0/tests/gmm_torture01_lusolve.cc b/resources/3rdparty/gmm-5.2/tests/gmm_torture01_lusolve.cc similarity index 94% rename from resources/3rdparty/gmm-5.0/tests/gmm_torture01_lusolve.cc rename to resources/3rdparty/gmm-5.2/tests/gmm_torture01_lusolve.cc index b163186d7..0b3369cc9 100644 --- a/resources/3rdparty/gmm-5.0/tests/gmm_torture01_lusolve.cc +++ b/resources/3rdparty/gmm-5.2/tests/gmm_torture01_lusolve.cc @@ -1,10 +1,10 @@ /*=========================================================================== - - Copyright (C) 2007-2015 Yves Renard, Julien Pommier. - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2007-2017 Yves Renard, Julien Pommier. + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -16,7 +16,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + ===========================================================================*/ // SQUARED_MATRIX_PARAM; // DENSE_VECTOR_PARAM; diff --git a/resources/3rdparty/gmm-5.0/tests/gmm_torture02_baseop.cc b/resources/3rdparty/gmm-5.2/tests/gmm_torture02_baseop.cc similarity index 92% rename from resources/3rdparty/gmm-5.0/tests/gmm_torture02_baseop.cc rename to resources/3rdparty/gmm-5.2/tests/gmm_torture02_baseop.cc index c9bab9a49..1bc737494 100644 --- a/resources/3rdparty/gmm-5.0/tests/gmm_torture02_baseop.cc +++ b/resources/3rdparty/gmm-5.2/tests/gmm_torture02_baseop.cc @@ -1,10 +1,10 @@ /*=========================================================================== - - Copyright (C) 2007-2015 Yves Renard, Julien Pommier. - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2007-2017 Yves Renard, Julien Pommier. + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -16,7 +16,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + ===========================================================================*/ // SQUARED_MATRIX_PARAM; // VECTOR_PARAM; diff --git a/resources/3rdparty/gmm-5.0/tests/gmm_torture05_mult.cc b/resources/3rdparty/gmm-5.2/tests/gmm_torture05_mult.cc similarity index 98% rename from resources/3rdparty/gmm-5.0/tests/gmm_torture05_mult.cc rename to resources/3rdparty/gmm-5.2/tests/gmm_torture05_mult.cc index b8fcce63c..a44f01b82 100644 --- a/resources/3rdparty/gmm-5.0/tests/gmm_torture05_mult.cc +++ b/resources/3rdparty/gmm-5.2/tests/gmm_torture05_mult.cc @@ -1,10 +1,10 @@ /*=========================================================================== - - Copyright (C) 2007-2015 Yves Renard, Julien Pommier. - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2007-2017 Yves Renard, Julien Pommier. + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -16,7 +16,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + ===========================================================================*/ // SQUARED_MATRIX_PARAM // VECTOR_PARAM; diff --git a/resources/3rdparty/gmm-5.0/tests/gmm_torture06_mat_mult.cc b/resources/3rdparty/gmm-5.2/tests/gmm_torture06_mat_mult.cc similarity index 96% rename from resources/3rdparty/gmm-5.0/tests/gmm_torture06_mat_mult.cc rename to resources/3rdparty/gmm-5.2/tests/gmm_torture06_mat_mult.cc index e716716b4..c30133701 100644 --- a/resources/3rdparty/gmm-5.0/tests/gmm_torture06_mat_mult.cc +++ b/resources/3rdparty/gmm-5.2/tests/gmm_torture06_mat_mult.cc @@ -1,10 +1,10 @@ /*=========================================================================== - - Copyright (C) 2007-2015 Yves Renard, Julien Pommier. - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2007-2017 Yves Renard, Julien Pommier. + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -16,7 +16,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + ===========================================================================*/ // RECTANGULAR_MATRIX_PARAM // RECTANGULAR_MATRIX_PARAM; diff --git a/resources/3rdparty/gmm-5.0/tests/gmm_torture10_qr.cc b/resources/3rdparty/gmm-5.2/tests/gmm_torture10_qr.cc similarity index 98% rename from resources/3rdparty/gmm-5.0/tests/gmm_torture10_qr.cc rename to resources/3rdparty/gmm-5.2/tests/gmm_torture10_qr.cc index 6538fd4c6..51ea571bb 100644 --- a/resources/3rdparty/gmm-5.0/tests/gmm_torture10_qr.cc +++ b/resources/3rdparty/gmm-5.2/tests/gmm_torture10_qr.cc @@ -1,10 +1,10 @@ /*=========================================================================== - - Copyright (C) 2007-2015 Yves Renard, Julien Pommier. - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2007-2017 Yves Renard, Julien Pommier. + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -16,7 +16,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + ===========================================================================*/ // RECTANGULAR_MATRIX_PARAM // SQUARED_MATRIX_PARAM @@ -203,7 +203,7 @@ bool test_procedure(const MAT1 &m1_, const MAT2 &m2_) { std::complex det1(gmm::lu_det(ca)), det2(1); implicit_qr_algorithm(ca, eigc, cq); for (size_type i = 0; i < m; ++i) det2 *= eigc[i]; - if (gmm::abs(det1 - det2) > (gmm::abs(det1)+gmm::abs(det2))/R(100)) + if (gmm::abs(det1 - det2) > (gmm::abs(det1)+gmm::abs(det2))/R(50)) GMM_ASSERT1(false, "Error in QR or det. det lu: " << det1 << " det qr: " << det2); if (print_debug) diff --git a/resources/3rdparty/gmm-5.0/tests/gmm_torture15_sub.cc b/resources/3rdparty/gmm-5.2/tests/gmm_torture15_sub.cc similarity index 91% rename from resources/3rdparty/gmm-5.0/tests/gmm_torture15_sub.cc rename to resources/3rdparty/gmm-5.2/tests/gmm_torture15_sub.cc index 54afb1c66..0a1441463 100644 --- a/resources/3rdparty/gmm-5.0/tests/gmm_torture15_sub.cc +++ b/resources/3rdparty/gmm-5.2/tests/gmm_torture15_sub.cc @@ -1,10 +1,10 @@ /*=========================================================================== - - Copyright (C) 2007-2015 Yves Renard, Julien Pommier. - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2007-2017 Yves Renard, Julien Pommier. + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -16,7 +16,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + ===========================================================================*/ // SQUARED_MATRIX_PARAM // VECTOR_PARAM; @@ -58,7 +58,7 @@ bool test_procedure(const MAT1 &m1_, const VECT1 &v1_, const VECT2 &v2_) { gmm::add(gmm::scaled(gmm::sub_vector(v1, gmm::sub_interval(0,n)), T(-1)), gmm::sub_vector(v2, gmm::sub_interval(0,n)), v3); if (!((error = gmm::vect_norm2(v3)) <= prec * R(20000) * cond)) - GMM_THROW(gmm::failure_error, "Error too large: "<< error); + GMM_ASSERT1(false, "Error too large: "<< error); } det = gmm::abs(gmm::lu_det(gmm::sub_matrix(m1, gmm::sub_slice(0,n,1)))); @@ -71,7 +71,7 @@ bool test_procedure(const MAT1 &m1_, const VECT1 &v1_, const VECT2 &v2_) { gmm::add(gmm::scaled(gmm::sub_vector(v1, gmm::sub_slice(0,n,1)), T(-1)), gmm::sub_vector(v2, gmm::sub_slice(0,n,1)), v3); if (!((error = gmm::vect_norm2(v3)) <= prec * R(20000) * cond)) - GMM_THROW(gmm::failure_error, "Error too large: "<< error); + GMM_ASSERT1(false, "Error too large: "<< error); } gmm::copy(gmm::identity_matrix(), gmm::sub_matrix(gmm::transposed(m1), @@ -88,7 +88,7 @@ bool test_procedure(const MAT1 &m1_, const VECT1 &v1_, const VECT2 &v2_) { gmm::sub_vector(v2, gmm::sub_interval(0,n)), gmm::scaled(v2, T(-1)), v1); if (!((error = gmm::vect_norm2(v1)) <= prec * R(2000))) - GMM_THROW(gmm::failure_error, "Error too large: " << error); + GMM_ASSERT1(false, "Error too large: " << error); if (nb_iter == 100) return true; return false; diff --git a/resources/3rdparty/gmm-5.0/tests/gmm_torture20_iterative_solvers.cc b/resources/3rdparty/gmm-5.2/tests/gmm_torture20_iterative_solvers.cc similarity index 94% rename from resources/3rdparty/gmm-5.0/tests/gmm_torture20_iterative_solvers.cc rename to resources/3rdparty/gmm-5.2/tests/gmm_torture20_iterative_solvers.cc index f0cba1aa0..94c622e04 100644 --- a/resources/3rdparty/gmm-5.0/tests/gmm_torture20_iterative_solvers.cc +++ b/resources/3rdparty/gmm-5.2/tests/gmm_torture20_iterative_solvers.cc @@ -1,10 +1,10 @@ /*=========================================================================== - - Copyright (C) 2007-2015 Yves Renard, Julien Pommier. - - This file is a part of GETFEM++ - - Getfem++ is free software; you can redistribute it and/or modify it + + Copyright (C) 2007-2017 Yves Renard, Julien Pommier. + + This file is a part of GetFEM++ + + GetFEM++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version along with the GCC Runtime Library @@ -16,7 +16,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - + ===========================================================================*/ // SQUARED_MATRIX_PARAM; // DENSE_VECTOR_PARAM; @@ -163,14 +163,15 @@ bool test_procedure(const MAT1 &m1_, const VECT1 &v1_, const VECT2 &v2_) { gmm::set_warning_level(3); } - R det = gmm::abs(gmm::lu_det(m1)), cond = gmm::condest(m1); - + R det = gmm::abs(gmm::lu_det(m1)); + if (det < sqrt(prec)*R(10)) return false; + R cond = gmm::condest(m1); if (print_debug) cout << "condition number = " << cond << " det = " << det << endl; if (det == R(0) && cond < R(1) / prec && cond != R(0)) GMM_ASSERT1(false, "Inconsistent condition number: " << cond); - if (sqrt(prec) * cond >= R(1)/R(100) || det < sqrt(prec)*R(10)) return false; + if (sqrt(prec) * cond >= R(1)/R(100)) return false; ++effexpe; cout << "."; cout.flush(); @@ -229,7 +230,7 @@ bool test_procedure(const MAT1 &m1_, const VECT1 &v1_, const VECT2 &v2_) { if (print_debug) cout << "\nGmres with ilutp preconditionner\n"; do_test(GMRES(), m1, v1, v2, P5b, cond); - if (sizeof(R) > 4 || m < 20) { + if (sizeof(R) > 5 || m < 15) { if (print_debug) cout << "\nQmr with no preconditionner\n"; do_test(QMR(), m1, v1, v2, P1, cond); @@ -252,8 +253,8 @@ bool test_procedure(const MAT1 &m1_, const VECT1 &v1_, const VECT2 &v2_) { gmm::copy(m1, m3); gmm::add(gmm::conjugated(m1), m3); gmm::copy(m2, m1); - gmm::cholesky_precond P6(m1); - gmm::choleskyt_precond P7(m1, 10, prec); + gmm::ildlt_precond P6(m1); + gmm::ildltt_precond P7(m1, 10, prec); if (!is_hermitian(m1, prec*R(100))) GMM_ASSERT1(false, "The matrix is not hermitian"); @@ -291,7 +292,10 @@ bool test_procedure(const MAT1 &m1_, const VECT1 &v1_, const VECT2 &v2_) { print_stat(P5b, "ilutp precond"); print_stat(P6, "ildlt precond"); print_stat(P7, "ildltt precond"); - if (ratio_max > 0.2) GMM_ASSERT1(false, "something wrong .."); + if (sizeof(R) > 4 && ratio_max > 0.16) + GMM_ASSERT1(false, "something wrong .."); + if (sizeof(R) <= 4 && ratio_max > 0.3) + GMM_ASSERT1(false, "something wrong .."); return true; } diff --git a/resources/3rdparty/gmm-5.0/tests/make_gmm_test.pl b/resources/3rdparty/gmm-5.2/tests/make_gmm_test.pl similarity index 98% rename from resources/3rdparty/gmm-5.0/tests/make_gmm_test.pl rename to resources/3rdparty/gmm-5.2/tests/make_gmm_test.pl index d0c307ea1..c2325b38e 100755 --- a/resources/3rdparty/gmm-5.0/tests/make_gmm_test.pl +++ b/resources/3rdparty/gmm-5.2/tests/make_gmm_test.pl @@ -1,8 +1,8 @@ -# Copyright (C) 2001-2015 Yves Renard +# Copyright (C) 2001-2017 Yves Renard # -# This file is a part of GETFEM++ +# This file is a part of GetFEM++ # -# Getfem++ is free software; you can redistribute it and/or modify it +# GetFEM++ is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation; either version 3 of the License, or # (at your option) any later version along with the GCC Runtime Library diff --git a/resources/3rdparty/modernjson/src/json.hpp b/resources/3rdparty/modernjson/src/json.hpp index 596095aff..1b279a804 100755 --- a/resources/3rdparty/modernjson/src/json.hpp +++ b/resources/3rdparty/modernjson/src/json.hpp @@ -5650,7 +5650,8 @@ Format](http://rfc7159.net/rfc7159) { case value_t::array: { - return *lhs.m_value.array < *rhs.m_value.array; + // Workaround for gcc 7.2.0, which parses array< as a template. + return (*lhs.m_value.array) < *rhs.m_value.array; } case value_t::object: { diff --git a/resources/3rdparty/sylvan/src/storm_wrapper.cpp b/resources/3rdparty/sylvan/src/storm_wrapper.cpp index fb92720d0..78d73c0c3 100644 --- a/resources/3rdparty/sylvan/src/storm_wrapper.cpp +++ b/resources/3rdparty/sylvan/src/storm_wrapper.cpp @@ -310,7 +310,11 @@ int storm_rational_number_equal_modulo_precision(int relative, storm_rational_nu storm::RationalNumber const& srn_p = *(storm::RationalNumber const*)precision; if (relative) { - return carl::abs(srn_a - srn_b)/srn_a < srn_p ? 1 : 0; + if (storm::utility::isZero(srn_a)) { + return storm::utility::isZero(srn_b); + } else { + return carl::abs(srn_a - srn_b)/srn_a < srn_p ? 1 : 0; + } } else { return carl::abs(srn_a - srn_b) < srn_p ? 1 : 0; } diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 588d0d330..fd2b3d3a3 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -179,6 +179,7 @@ namespace storm { auto counterexampleGeneratorSettings = storm::settings::getModule(); storm::builder::BuilderOptions options(createFormulasToRespect(input.properties)); options.setBuildChoiceLabels(ioSettings.isBuildChoiceLabelsSet()); + options.setBuildStateValuations(ioSettings.isBuildStateValuationsSet()); options.setBuildChoiceOrigins(counterexampleGeneratorSettings.isMinimalCommandSetGenerationSet()); options.setBuildAllLabels(ioSettings.isBuildFullModelSet()); options.setBuildAllRewardModels(ioSettings.isBuildFullModelSet()); @@ -220,7 +221,7 @@ namespace storm { modelBuildingWatch.stop(); if (result) { - STORM_PRINT_AND_LOG("Time for model construction: " << modelBuildingWatch << "." << std::endl << std::endl); + STORM_PRINT("Time for model construction: " << modelBuildingWatch << "." << std::endl << std::endl); } return result; @@ -332,23 +333,23 @@ namespace storm { preprocessingWatch.stop(); if (result.second) { - STORM_PRINT_AND_LOG(std::endl << "Time for model preprocessing: " << preprocessingWatch << "." << std::endl << std::endl); + STORM_PRINT(std::endl << "Time for model preprocessing: " << preprocessingWatch << "." << std::endl << std::endl); } return result; } void printComputingCounterexample(storm::jani::Property const& property) { - STORM_PRINT_AND_LOG("Computing counterexample for property " << *property.getRawFormula() << " ..." << std::endl); + STORM_PRINT("Computing counterexample for property " << *property.getRawFormula() << " ..." << std::endl); } void printCounterexample(std::shared_ptr const& counterexample, storm::utility::Stopwatch* watch = nullptr) { if (counterexample) { - STORM_PRINT_AND_LOG(*counterexample << std::endl); + STORM_PRINT(*counterexample << std::endl); if (watch) { - STORM_PRINT_AND_LOG("Time for computation: " << *watch << "." << std::endl); + STORM_PRINT("Time for computation: " << *watch << "." << std::endl); } } else { - STORM_PRINT_AND_LOG(" failed." << std::endl); + STORM_PRINT(" failed." << std::endl); } } @@ -395,19 +396,19 @@ namespace storm { if (result->isQuantitative()) { switch (ft) { case storm::modelchecker::FilterType::VALUES: - STORM_PRINT_AND_LOG(*result); + STORM_PRINT(*result); break; case storm::modelchecker::FilterType::SUM: - STORM_PRINT_AND_LOG(result->asQuantitativeCheckResult().sum()); + STORM_PRINT(result->asQuantitativeCheckResult().sum()); break; case storm::modelchecker::FilterType::AVG: - STORM_PRINT_AND_LOG(result->asQuantitativeCheckResult().average()); + STORM_PRINT(result->asQuantitativeCheckResult().average()); break; case storm::modelchecker::FilterType::MIN: - STORM_PRINT_AND_LOG(result->asQuantitativeCheckResult().getMin()); + STORM_PRINT(result->asQuantitativeCheckResult().getMin()); break; case storm::modelchecker::FilterType::MAX: - STORM_PRINT_AND_LOG(result->asQuantitativeCheckResult().getMax()); + STORM_PRINT(result->asQuantitativeCheckResult().getMax()); break; case storm::modelchecker::FilterType::ARGMIN: case storm::modelchecker::FilterType::ARGMAX: @@ -420,16 +421,16 @@ namespace storm { } else { switch (ft) { case storm::modelchecker::FilterType::VALUES: - STORM_PRINT_AND_LOG(*result << std::endl); + STORM_PRINT(*result << std::endl); break; case storm::modelchecker::FilterType::EXISTS: - STORM_PRINT_AND_LOG(result->asQualitativeCheckResult().existsTrue()); + STORM_PRINT(result->asQualitativeCheckResult().existsTrue()); break; case storm::modelchecker::FilterType::FORALL: - STORM_PRINT_AND_LOG(result->asQualitativeCheckResult().forallTrue()); + STORM_PRINT(result->asQualitativeCheckResult().forallTrue()); break; case storm::modelchecker::FilterType::COUNT: - STORM_PRINT_AND_LOG(result->asQualitativeCheckResult().count()); + STORM_PRINT(result->asQualitativeCheckResult().count()); break; case storm::modelchecker::FilterType::ARGMIN: case storm::modelchecker::FilterType::ARGMAX: @@ -441,11 +442,11 @@ namespace storm { STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Filter type only defined for quantitative results."); } } - STORM_PRINT_AND_LOG(std::endl); + STORM_PRINT(std::endl); } void printModelCheckingProperty(storm::jani::Property const& property) { - STORM_PRINT_AND_LOG(std::endl << "Model checking property " << *property.getRawFormula() << " ..." << std::endl); + STORM_PRINT(std::endl << "Model checking property " << *property.getRawFormula() << " ..." << std::endl); } template @@ -453,13 +454,13 @@ namespace storm { if (result) { std::stringstream ss; ss << "'" << *property.getFilter().getStatesFormula() << "'"; - STORM_PRINT_AND_LOG("Result (for " << (property.getFilter().getStatesFormula()->isInitialFormula() ? "initial" : ss.str()) << " states): "); + STORM_PRINT("Result (for " << (property.getFilter().getStatesFormula()->isInitialFormula() ? "initial" : ss.str()) << " states): "); printFilteredResult(result, property.getFilter().getFilterType()); if (watch) { - STORM_PRINT_AND_LOG("Time for model checking: " << *watch << "." << std::endl); + STORM_PRINT("Time for model checking: " << *watch << "." << std::endl); } } else { - STORM_PRINT_AND_LOG(" failed, property is unsupported by selected engine/settings." << std::endl); + STORM_PRINT(" failed, property is unsupported by selected engine/settings." << std::endl); } } @@ -630,6 +631,8 @@ namespace storm { std::shared_ptr model = buildPreprocessExportModelWithValueTypeAndDdlib(input, engine); if (model) { + STORM_LOG_THROW(model->isSparseModel() || !storm::settings::getModule().isSoundSet(), storm::exceptions::NotSupportedException, "Forcing soundness is currently only supported for sparse models."); + if (coreSettings.isCounterexampleSet()) { auto ioSettings = storm::settings::getModule(); generateCounterexamples(model, input); @@ -644,7 +647,7 @@ namespace storm { template void processInputWithValueType(SymbolicInput const& input) { auto coreSettings = storm::settings::getModule(); - + if (coreSettings.getDdLibraryType() == storm::dd::DdType::CUDD) { processInputWithValueTypeAndDdlib(input); } else { diff --git a/src/storm-dft/transformations/DftToGspnTransformator.cpp b/src/storm-dft/transformations/DftToGspnTransformator.cpp index 8c3ef0448..975d01f4a 100644 --- a/src/storm-dft/transformations/DftToGspnTransformator.cpp +++ b/src/storm-dft/transformations/DftToGspnTransformator.cpp @@ -416,7 +416,7 @@ namespace storm { cucNodes.push_back(nodeCUC); builder.setPlaceLayoutInfo(nodeCUC, storm::gspn::LayoutInfo(xcenter-9.0+j*14.0, ycenter+5.0)); if (j > 0) { - uint64 tclaim = builder.addImmediateTransition(getFailPriority(dftSpare), 0.0, dftSpare->name() + "_claim_" + child->name()); + uint64_t tclaim = builder.addImmediateTransition(getFailPriority(dftSpare), 0.0, dftSpare->name() + "_claim_" + child->name()); builder.setTransitionLayoutInfo(tclaim, storm::gspn::LayoutInfo(xcenter-9.0+j*14.0, ycenter)); builder.addInhibitionArc(unavailableNodes.at(child->id()), tclaim); builder.addInputArc(considerNodes.back(), tclaim); diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index 3d8d18f8b..119e3791d 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -230,15 +230,15 @@ namespace storm { if (lowerResultBound) solver->setLowerBound(lowerResultBound.get()); if (upperResultBound) solver->setUpperBound(upperResultBound.get()); if (!stepBound) solver->setTrackScheduler(true); - if (storm::solver::minimize(dirForParameters) && minSchedChoices && !stepBound) solver->setSchedulerHint(std::move(minSchedChoices.get())); - if (storm::solver::maximize(dirForParameters) && maxSchedChoices && !stepBound) solver->setSchedulerHint(std::move(maxSchedChoices.get())); - if (this->currentCheckTask->isBoundSet() && solver->hasSchedulerHint()) { + if (storm::solver::minimize(dirForParameters) && minSchedChoices && !stepBound) solver->setInitialScheduler(std::move(minSchedChoices.get())); + if (storm::solver::maximize(dirForParameters) && maxSchedChoices && !stepBound) solver->setInitialScheduler(std::move(maxSchedChoices.get())); + if (this->currentCheckTask->isBoundSet() && solver->hasInitialScheduler()) { // If we reach this point, we know that after applying the hint, the x-values can only become larger (if we maximize) or smaller (if we minimize). std::unique_ptr> termCond; storm::storage::BitVector relevantStatesInSubsystem = this->currentCheckTask->isOnlyInitialStatesRelevantSet() ? this->parametricModel->getInitialStates() % maybeStates : storm::storage::BitVector(maybeStates.getNumberOfSetBits(), true); if (storm::solver::minimize(dirForParameters)) { // Terminate if the value for ALL relevant states is already below the threshold - termCond = std::make_unique> (relevantStatesInSubsystem, this->currentCheckTask->getBoundThreshold(), true, false); + termCond = std::make_unique> (relevantStatesInSubsystem, true, this->currentCheckTask->getBoundThreshold(), false); } else { // Terminate if the value for ALL relevant states is already above the threshold termCond = std::make_unique> (relevantStatesInSubsystem, true, this->currentCheckTask->getBoundThreshold(), true); diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp index 65e16d628..19ac39b62 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp @@ -272,7 +272,7 @@ namespace storm { storm::storage::BitVector relevantStatesInSubsystem = this->currentCheckTask->isOnlyInitialStatesRelevantSet() ? this->parametricModel->getInitialStates() % maybeStates : storm::storage::BitVector(maybeStates.getNumberOfSetBits(), true); if (storm::solver::minimize(dirForParameters)) { // Terminate if the value for ALL relevant states is already below the threshold - termCond = std::make_unique> (relevantStatesInSubsystem, this->currentCheckTask->getBoundThreshold(), true, false); + termCond = std::make_unique> (relevantStatesInSubsystem, true, this->currentCheckTask->getBoundThreshold(), false); } else { // Terminate if the value for ALL relevant states is already above the threshold termCond = std::make_unique> (relevantStatesInSubsystem, true, this->currentCheckTask->getBoundThreshold(), true); diff --git a/src/storm-pgcl-cli/CMakeLists.txt b/src/storm-pgcl-cli/CMakeLists.txt index 4778d1e93..4f2799d4d 100644 --- a/src/storm-pgcl-cli/CMakeLists.txt +++ b/src/storm-pgcl-cli/CMakeLists.txt @@ -2,5 +2,7 @@ add_executable(storm-pgcl-cli ${PROJECT_SOURCE_DIR}/src/storm-pgcl-cli/storm-pgc target_link_libraries(storm-pgcl-cli storm-pgcl storm-cli-utilities) set_target_properties(storm-pgcl-cli PROPERTIES OUTPUT_NAME "storm-pgcl") +add_dependencies(binaries storm-pgcl-cli) + # installation install(TARGETS storm-pgcl-cli RUNTIME DESTINATION bin LIBRARY DESTINATION lib OPTIONAL) \ No newline at end of file diff --git a/src/storm/adapters/GmmxxAdapter.cpp b/src/storm/adapters/GmmxxAdapter.cpp new file mode 100644 index 000000000..4210a00ee --- /dev/null +++ b/src/storm/adapters/GmmxxAdapter.cpp @@ -0,0 +1,53 @@ +#include "storm/adapters/GmmxxAdapter.h" + +#include + +#include "storm/adapters/RationalNumberAdapter.h" +#include "storm/adapters/RationalFunctionAdapter.h" + +#include "storm/utility/macros.h" + +namespace storm { + namespace adapters { + + template + std::unique_ptr> GmmxxAdapter::toGmmxxSparseMatrix(storm::storage::SparseMatrix const& matrix) { + uint_fast64_t realNonZeros = matrix.getEntryCount(); + STORM_LOG_DEBUG("Converting " << matrix.getRowCount() << "x" << matrix.getColumnCount() << " matrix with " << realNonZeros << " non-zeros to gmm++ format."); + + // Prepare the resulting matrix. + std::unique_ptr> result(new gmm::csr_matrix(matrix.getRowCount(), matrix.getColumnCount())); + + // Copy Row Indications + std::copy(matrix.rowIndications.begin(), matrix.rowIndications.end(), result->jc.begin()); + + // Copy columns and values. + std::vector values; + values.reserve(matrix.getEntryCount()); + + // To match the correct vector type for gmm, we create the vector with the exact same type. + decltype(result->ir) columns; + columns.reserve(matrix.getEntryCount()); + + for (auto const& entry : matrix) { + columns.emplace_back(entry.getColumn()); + values.emplace_back(entry.getValue()); + } + + std::swap(result->ir, columns); + std::swap(result->pr, values); + + STORM_LOG_DEBUG("Done converting matrix to gmm++ format."); + + return result; + } + + template class GmmxxAdapter; + +#ifdef STORM_HAVE_CARL + template class GmmxxAdapter; + template class GmmxxAdapter; +#endif + + } +} diff --git a/src/storm/adapters/GmmxxAdapter.h b/src/storm/adapters/GmmxxAdapter.h index dd14ddc4d..a5e139db0 100644 --- a/src/storm/adapters/GmmxxAdapter.h +++ b/src/storm/adapters/GmmxxAdapter.h @@ -1,59 +1,23 @@ -#ifndef STORM_ADAPTERS_GMMXXADAPTER_H_ -#define STORM_ADAPTERS_GMMXXADAPTER_H_ +#pragma once -#include #include #include "storm/utility/gmm.h" #include "storm/storage/SparseMatrix.h" -#include "storm/utility/macros.h" - namespace storm { - namespace adapters { + template class GmmxxAdapter { public: /*! * Converts a sparse matrix into a sparse matrix in the gmm++ format. * @return A pointer to a row-major sparse matrix in gmm++ format. */ - template - static std::unique_ptr> toGmmxxSparseMatrix(storm::storage::SparseMatrix const& matrix) { - uint_fast64_t realNonZeros = matrix.getEntryCount(); - STORM_LOG_DEBUG("Converting " << matrix.getRowCount() << "x" << matrix.getColumnCount() << " matrix with " << realNonZeros << " non-zeros to gmm++ format."); - - // Prepare the resulting matrix. - std::unique_ptr> result(new gmm::csr_matrix(matrix.getRowCount(), matrix.getColumnCount())); - - // Copy Row Indications - std::copy(matrix.rowIndications.begin(), matrix.rowIndications.end(), result->jc.begin()); - - // Copy columns and values. - std::vector values; - values.reserve(matrix.getEntryCount()); - - // To match the correct vector type for gmm, we create the vector with the exact same type. - decltype(result->ir) columns; - columns.reserve(matrix.getEntryCount()); - - for (auto const& entry : matrix) { - columns.emplace_back(entry.getColumn()); - values.emplace_back(entry.getValue()); - } - - std::swap(result->ir, columns); - std::swap(result->pr, values); - - STORM_LOG_DEBUG("Done converting matrix to gmm++ format."); - - return result; - } + static std::unique_ptr> toGmmxxSparseMatrix(storm::storage::SparseMatrix const& matrix); }; - } // namespace adapters -} // namespace storm - -#endif /* STORM_ADAPTERS_GMMXXADAPTER_H_ */ + } +} diff --git a/src/storm/builder/BuilderOptions.cpp b/src/storm/builder/BuilderOptions.cpp index b0d2641bd..2ee5bf37c 100644 --- a/src/storm/builder/BuilderOptions.cpp +++ b/src/storm/builder/BuilderOptions.cpp @@ -4,6 +4,7 @@ #include "storm/settings/SettingsManager.h" #include "storm/settings/modules/IOSettings.h" +#include "storm/settings/modules/GeneralSettings.h" #include "storm/utility/macros.h" #include "storm/exceptions/InvalidSettingsException.h" @@ -35,7 +36,7 @@ namespace storm { return boost::get(labelOrExpression); } - BuilderOptions::BuilderOptions(bool buildAllRewardModels, bool buildAllLabels) : buildAllRewardModels(buildAllRewardModels), buildAllLabels(buildAllLabels), buildChoiceLabels(false), buildStateValuations(false), buildChoiceOrigins(false), explorationChecks(false), explorationShowProgress(false), explorationShowProgressDelay(0) { + BuilderOptions::BuilderOptions(bool buildAllRewardModels, bool buildAllLabels) : buildAllRewardModels(buildAllRewardModels), buildAllLabels(buildAllLabels), buildChoiceLabels(false), buildStateValuations(false), buildChoiceOrigins(false), explorationChecks(false), showProgress(false), showProgressDelay(0) { // Intentionally left empty. } @@ -54,9 +55,11 @@ namespace storm { } } - explorationChecks = storm::settings::getModule().isExplorationChecksSet(); - explorationShowProgress = storm::settings::getModule().isExplorationShowProgressSet(); - explorationShowProgressDelay = storm::settings::getModule().getExplorationShowProgressDelay(); + auto const& ioSettings = storm::settings::getModule(); + auto const& generalSettings = storm::settings::getModule(); + explorationChecks = ioSettings.isExplorationChecksSet(); + showProgress = generalSettings.isVerboseSet(); + showProgressDelay = generalSettings.getShowProgressDelay(); } void BuilderOptions::preserveFormula(storm::logic::Formula const& formula) { @@ -166,12 +169,12 @@ namespace storm { return explorationChecks; } - bool BuilderOptions::isExplorationShowProgressSet() const { - return explorationShowProgress; + bool BuilderOptions::isShowProgressSet() const { + return showProgress; } - uint64_t BuilderOptions::getExplorationShowProgressDelay() const { - return explorationShowProgressDelay; + uint64_t BuilderOptions::getShowProgressDelay() const { + return showProgressDelay; } BuilderOptions& BuilderOptions::setExplorationChecks(bool newValue) { diff --git a/src/storm/builder/BuilderOptions.h b/src/storm/builder/BuilderOptions.h index f3a6edfbf..fe56994c7 100644 --- a/src/storm/builder/BuilderOptions.h +++ b/src/storm/builder/BuilderOptions.h @@ -106,8 +106,8 @@ namespace storm { bool isBuildAllRewardModelsSet() const; bool isBuildAllLabelsSet() const; bool isExplorationChecksSet() const; - bool isExplorationShowProgressSet() const; - uint64_t getExplorationShowProgressDelay() const; + bool isShowProgressSet() const; + uint64_t getShowProgressDelay() const; /** * Should all reward models be built? If not set, only required reward models are build. @@ -190,10 +190,10 @@ namespace storm { bool explorationChecks; /// A flag that stores whether the progress of exploration is to be printed. - bool explorationShowProgress; + bool showProgress; /// The delay for printing progress information. - uint64_t explorationShowProgressDelay; + uint64_t showProgressDelay; }; } diff --git a/src/storm/builder/ExplicitModelBuilder.cpp b/src/storm/builder/ExplicitModelBuilder.cpp index 665190e6c..7a552e9bd 100644 --- a/src/storm/builder/ExplicitModelBuilder.cpp +++ b/src/storm/builder/ExplicitModelBuilder.cpp @@ -240,13 +240,13 @@ namespace storm { ++currentRowGroup; } - if (generator->getOptions().isExplorationShowProgressSet()) { + if (generator->getOptions().isShowProgressSet()) { ++numberOfExploredStatesSinceLastMessage; ++numberOfExploredStates; auto now = std::chrono::high_resolution_clock::now(); auto durationSinceLastMessage = std::chrono::duration_cast(now - timeOfLastMessage).count(); - if (static_cast(durationSinceLastMessage) >= generator->getOptions().getExplorationShowProgressDelay()) { + if (static_cast(durationSinceLastMessage) >= generator->getOptions().getShowProgressDelay()) { auto statesPerSecond = numberOfExploredStatesSinceLastMessage / durationSinceLastMessage; auto durationSinceStart = std::chrono::duration_cast(now - timeOfStart).count(); std::cout << "Explored " << numberOfExploredStates << " states in " << durationSinceStart << " seconds (currently " << statesPerSecond << " states per second)." << std::endl; diff --git a/src/storm/builder/jit/ExplicitJitJaniModelBuilder.cpp b/src/storm/builder/jit/ExplicitJitJaniModelBuilder.cpp index a550ee130..54779b96a 100644 --- a/src/storm/builder/jit/ExplicitJitJaniModelBuilder.cpp +++ b/src/storm/builder/jit/ExplicitJitJaniModelBuilder.cpp @@ -528,13 +528,13 @@ namespace storm { } modelData["exploration_checks"] = cpptempl::make_data(list); list = cpptempl::data_list(); - if (options.isExplorationShowProgressSet()) { + if (options.isShowProgressSet()) { list.push_back(cpptempl::data_map()); } modelData["expl_progress"] = cpptempl::make_data(list); std::stringstream progressDelayStream; - progressDelayStream << options.getExplorationShowProgressDelay(); + progressDelayStream << options.getShowProgressDelay(); modelData["expl_progress_interval"] = cpptempl::make_data(progressDelayStream.str()); list = cpptempl::data_list(); if (std::is_same::value) { diff --git a/src/storm/counterexamples/MILPMinimalLabelSetGenerator.h b/src/storm/counterexamples/MILPMinimalLabelSetGenerator.h index dff7a2808..a7d132e89 100644 --- a/src/storm/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/storm/counterexamples/MILPMinimalLabelSetGenerator.h @@ -16,6 +16,8 @@ #include "storm/exceptions/InvalidArgumentException.h" #include "storm/exceptions/InvalidStateException.h" +#include "storm/solver/MinMaxLinearEquationSolver.h" + #include "storm/counterexamples/PrismHighLevelCounterexample.h" #include "storm/utility/graph.h" diff --git a/src/storm/exceptions/FormatUnsupportedBySolverException.h b/src/storm/exceptions/FormatUnsupportedBySolverException.h new file mode 100644 index 000000000..2f7d2bf65 --- /dev/null +++ b/src/storm/exceptions/FormatUnsupportedBySolverException.h @@ -0,0 +1,13 @@ +#pragma once + +#include "storm/exceptions/BaseException.h" +#include "storm/exceptions/ExceptionMacros.h" + +namespace storm { + namespace exceptions { + + STORM_NEW_EXCEPTION(FormatUnsupportedBySolverException) + + } // namespace exceptions +} // namespace storm + diff --git a/src/storm/exceptions/InvalidSolverSettingsException.h b/src/storm/exceptions/InvalidSolverSettingsException.h new file mode 100644 index 000000000..0580fb0cc --- /dev/null +++ b/src/storm/exceptions/InvalidSolverSettingsException.h @@ -0,0 +1,12 @@ +#pragma once + +#include "storm/exceptions/BaseException.h" +#include "storm/exceptions/ExceptionMacros.h" + +namespace storm { + namespace exceptions { + + STORM_NEW_EXCEPTION(InvalidSolverSettingsException) + + } // namespace exceptions +} // namespace storm diff --git a/src/storm/exceptions/UncheckedRequirementException.h b/src/storm/exceptions/UncheckedRequirementException.h new file mode 100644 index 000000000..f902c6ee5 --- /dev/null +++ b/src/storm/exceptions/UncheckedRequirementException.h @@ -0,0 +1,12 @@ +#pragma once + +#include "storm/exceptions/BaseException.h" +#include "storm/exceptions/ExceptionMacros.h" + +namespace storm { + namespace exceptions { + + STORM_NEW_EXCEPTION(UncheckedRequirementException) + + } // namespace exceptions +} // namespace storm diff --git a/src/storm/exceptions/UnmetRequirementException.h b/src/storm/exceptions/UnmetRequirementException.h new file mode 100644 index 000000000..3a7b70312 --- /dev/null +++ b/src/storm/exceptions/UnmetRequirementException.h @@ -0,0 +1,12 @@ +#pragma once + +#include "storm/exceptions/BaseException.h" +#include "storm/exceptions/ExceptionMacros.h" + +namespace storm { + namespace exceptions { + + STORM_NEW_EXCEPTION(UnmetRequirementException) + + } // namespace exceptions +} // namespace storm diff --git a/src/storm/modelchecker/CheckTask.h b/src/storm/modelchecker/CheckTask.h index 828f85215..cc0de06c0 100644 --- a/src/storm/modelchecker/CheckTask.h +++ b/src/storm/modelchecker/CheckTask.h @@ -228,10 +228,18 @@ namespace storm { ModelCheckerHint const& getHint() const { return *hint; } + ModelCheckerHint& getHint() { return *hint; } + /*! + * Conversion operator that strips the type of the formula. + */ + operator CheckTask() const { + return this->substituteFormula(this->getFormula()); + } + private: /*! * Creates a task object with the given options. diff --git a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp index facfd3da2..5443c27ee 100644 --- a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -72,7 +72,7 @@ namespace storm { upperBound = storm::utility::infinity(); } - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeBoundedUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), this->getModel().getExitRateVector(), checkTask.isQualitativeSet(), lowerBound, upperBound, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), this->getModel().getExitRateVector(), checkTask.isQualitativeSet(), lowerBound, upperBound, *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -92,7 +92,7 @@ namespace storm { std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -100,7 +100,7 @@ namespace storm { std::unique_ptr SparseCtmcCslModelChecker::computeInstantaneousRewards(storm::logic::RewardMeasureType, CheckTask const& checkTask) { storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(!rewardPathFormula.isStepBounded(), storm::exceptions::NotImplementedException, "Currently step-bounded properties on CTMCs are not supported."); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeInstantaneousRewards(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getBound(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeInstantaneousRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getBound(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -108,7 +108,7 @@ namespace storm { std::unique_ptr SparseCtmcCslModelChecker::computeCumulativeRewards(storm::logic::RewardMeasureType, CheckTask const& checkTask) { storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(!rewardPathFormula.isStepBounded(), storm::exceptions::NotImplementedException, "Currently step-bounded properties on CTMCs are not supported."); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeCumulativeRewards(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getNonStrictBound(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeCumulativeRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getNonStrictBound(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -118,7 +118,7 @@ namespace storm { std::unique_ptr subResultPointer = this->check(eventuallyFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -129,14 +129,14 @@ namespace storm { ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); 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(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), probabilityMatrix, subResult.getTruthValuesVector(), &this->getModel().getExitRateVector(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template std::unique_ptr SparseCtmcCslModelChecker::computeLongRunAverageRewards(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) { storm::storage::SparseMatrix probabilityMatrix = storm::modelchecker::helper::SparseCtmcCslHelper::computeProbabilityMatrix(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector()); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageRewards(probabilityMatrix, checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), &this->getModel().getExitRateVector(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal(this->getModel(), checkTask), probabilityMatrix, checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), &this->getModel().getExitRateVector(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -146,7 +146,7 @@ namespace storm { 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(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityTimes(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } diff --git a/src/storm/modelchecker/csl/helper/HybridCtmcCslHelper.cpp b/src/storm/modelchecker/csl/helper/HybridCtmcCslHelper.cpp index cb046cfb1..59e5b2ea2 100644 --- a/src/storm/modelchecker/csl/helper/HybridCtmcCslHelper.cpp +++ b/src/storm/modelchecker/csl/helper/HybridCtmcCslHelper.cpp @@ -301,7 +301,7 @@ namespace storm { storm::storage::SparseMatrix explicitProbabilityMatrix = probabilityMatrix.toMatrix(odd, odd); std::vector explicitExitRateVector = exitRateVector.toVector(odd); - std::vector result = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(explicitProbabilityMatrix, psiStates.toVector(odd), &explicitExitRateVector, linearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal(), explicitProbabilityMatrix, psiStates.toVector(odd), &explicitExitRateVector, linearEquationSolverFactory); return std::unique_ptr(new HybridQuantitativeCheckResult(model.getReachableStates(), model.getManager().getBddZero(), model.getManager().template getAddZero(), model.getReachableStates(), std::move(odd), std::move(result))); } @@ -318,7 +318,7 @@ namespace storm { storm::storage::SparseMatrix explicitProbabilityMatrix = probabilityMatrix.toMatrix(odd, odd); std::vector explicitExitRateVector = exitRateVector.toVector(odd); - std::vector result = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageRewards(explicitProbabilityMatrix, rewardModel.getTotalRewardVector(probabilityMatrix, model.getColumnVariables(), exitRateVector, true).toVector(odd), &explicitExitRateVector, linearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal(), explicitProbabilityMatrix, rewardModel.getTotalRewardVector(probabilityMatrix, model.getColumnVariables(), exitRateVector, true).toVector(odd), &explicitExitRateVector, linearEquationSolverFactory); return std::unique_ptr(new HybridQuantitativeCheckResult(model.getReachableStates(), model.getManager().getBddZero(), model.getManager().template getAddZero(), model.getReachableStates(), std::move(odd), std::move(result))); } diff --git a/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.cpp b/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.cpp index b574cabd1..430b16224 100644 --- a/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.cpp +++ b/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.cpp @@ -22,18 +22,19 @@ #include "storm/exceptions/InvalidOperationException.h" #include "storm/exceptions/InvalidStateException.h" #include "storm/exceptions/InvalidPropertyException.h" +#include "storm/exceptions/FormatUnsupportedBySolverException.h" namespace storm { namespace modelchecker { namespace helper { template ::SupportsExponential, int>::type> - std::vector SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { uint_fast64_t numberOfStates = rateMatrix.getRowCount(); // If the time bounds are [0, inf], we rather call untimed reachability. if (storm::utility::isZero(lowerBound) && upperBound == storm::utility::infinity()) { - return computeUntilProbabilities(rateMatrix, backwardTransitions, exitRates, phiStates, psiStates, qualitative, linearEquationSolverFactory); + return computeUntilProbabilities(std::move(goal), rateMatrix, backwardTransitions, exitRates, phiStates, psiStates, qualitative, linearEquationSolverFactory); } // From this point on, we know that we have to solve a more complicated problem [t, t'] with either t != 0 @@ -88,7 +89,7 @@ namespace storm { // Start by computing the (unbounded) reachability probabilities of reaching psi states while // staying in phi states. - result = computeUntilProbabilities(rateMatrix, backwardTransitions, exitRates, phiStates, psiStates, qualitative, linearEquationSolverFactory); + result = computeUntilProbabilities(storm::solver::SolveGoal(), rateMatrix, backwardTransitions, exitRates, phiStates, psiStates, qualitative, linearEquationSolverFactory); // Determine the set of states that must be considered further. storm::storage::BitVector relevantStates = statesWithProbabilityGreater0 & phiStates; @@ -194,13 +195,13 @@ namespace storm { } template ::SupportsExponential, int>::type> - std::vector SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::storage::SparseMatrix const&, storm::storage::SparseMatrix const&, storm::storage::BitVector const&, storm::storage::BitVector const&, std::vector const&, bool, double, double, storm::solver::LinearEquationSolverFactory const&) { + std::vector SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const&, storm::storage::SparseMatrix const&, storm::storage::BitVector const&, storm::storage::BitVector const&, std::vector const&, bool, double, double, storm::solver::LinearEquationSolverFactory const&) { STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Computing bounded until probabilities is unsupported for this value type."); } template - std::vector SparseCtmcCslHelper::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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { - return SparseDtmcPrctlHelper::computeUntilProbabilities(computeProbabilityMatrix(rateMatrix, exitRateVector), backwardTransitions, phiStates, psiStates, qualitative, linearEquationSolverFactory); + std::vector SparseCtmcCslHelper::computeUntilProbabilities(storm::solver::SolveGoal&& goal, 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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + return SparseDtmcPrctlHelper::computeUntilProbabilities(std::move(goal), computeProbabilityMatrix(rateMatrix, exitRateVector), backwardTransitions, phiStates, psiStates, qualitative, linearEquationSolverFactory); } template @@ -209,7 +210,7 @@ namespace storm { } template ::SupportsExponential, int>::type> - std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { // Only compute the result if the model has a state-based reward model. STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); @@ -235,12 +236,12 @@ namespace storm { } template ::SupportsExponential, int>::type> - std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::storage::SparseMatrix const&, std::vector const&, RewardModelType const&, double, storm::solver::LinearEquationSolverFactory const&) { + std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const&, std::vector const&, RewardModelType const&, double, storm::solver::LinearEquationSolverFactory const&) { STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Computing instantaneous rewards is unsupported for this value type."); } template ::SupportsExponential, int>::type> - std::vector SparseCtmcCslHelper::computeCumulativeRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseCtmcCslHelper::computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { // Only compute the result if the model has a state-based reward model. STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); @@ -271,12 +272,12 @@ namespace storm { } template ::SupportsExponential, int>::type> - std::vector SparseCtmcCslHelper::computeCumulativeRewards(storm::storage::SparseMatrix const&, std::vector const&, RewardModelType const&, double, storm::solver::LinearEquationSolverFactory const&) { + std::vector SparseCtmcCslHelper::computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const&, std::vector const&, RewardModelType const&, double, storm::solver::LinearEquationSolverFactory const&) { STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Computing cumulative rewards is unsupported for this value type."); } template - std::vector SparseCtmcCslHelper::computeReachabilityTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseCtmcCslHelper::computeReachabilityTimes(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { // Compute expected time on CTMC by reduction to DTMC with rewards. storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); @@ -292,11 +293,11 @@ namespace storm { } } - return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); + return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(std::move(goal), probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); } template - std::vector SparseCtmcCslHelper::computeReachabilityRewards(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseCtmcCslHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); @@ -323,11 +324,11 @@ namespace storm { totalRewardVector = rewardModel.getStateActionRewardVector(); } - return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); + return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(std::move(goal), probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); } template - std::vector SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { // If there are no goal states, we avoid the computation and directly return zero. uint_fast64_t numberOfStates = probabilityMatrix.getRowCount(); @@ -343,7 +344,7 @@ namespace storm { ValueType zero = storm::utility::zero(); ValueType one = storm::utility::one(); - return computeLongRunAverages(probabilityMatrix, + return computeLongRunAverages(std::move(goal), probabilityMatrix, [&zero, &one, &psiStates] (storm::storage::sparse::state_type const& state) -> ValueType { if (psiStates.get(state)) { return one; @@ -355,16 +356,16 @@ namespace storm { } template - std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::storage::SparseMatrix const& probabilityMatrix, RewardModelType const& rewardModel, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, RewardModelType const& rewardModel, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { // Only compute the result if the model has a state-based reward model. STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); - return computeLongRunAverageRewards(probabilityMatrix, rewardModel.getTotalRewardVector(probabilityMatrix, *exitRateVector), exitRateVector, linearEquationSolverFactory); + return computeLongRunAverageRewards(std::move(goal), probabilityMatrix, rewardModel.getTotalRewardVector(probabilityMatrix, *exitRateVector), exitRateVector, linearEquationSolverFactory); } template - std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::storage::SparseMatrix const& probabilityMatrix, std::vector const& stateRewardVector, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { - return computeLongRunAverages(probabilityMatrix, + std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, std::vector const& stateRewardVector, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + return computeLongRunAverages(std::move(goal), probabilityMatrix, [&stateRewardVector] (storm::storage::sparse::state_type const& state) -> ValueType { return stateRewardVector[state]; }, @@ -373,7 +374,7 @@ namespace storm { } template - std::vector SparseCtmcCslHelper::computeLongRunAverages(storm::storage::SparseMatrix const& probabilityMatrix, std::function const& valueGetter, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory){ + std::vector SparseCtmcCslHelper::computeLongRunAverages(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, std::function const& valueGetter, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory){ uint_fast64_t numberOfStates = probabilityMatrix.getRowCount(); // Start by decomposing the CTMC into its BSCCs. @@ -489,6 +490,8 @@ namespace storm { bsccEquationSystem = builder.build(); { + // Check whether we have the right input format for the solver. + STORM_LOG_THROW(linearEquationSolverFactory.getEquationProblemFormat() == storm::solver::LinearEquationSolverProblemFormat::EquationSystem, storm::exceptions::FormatUnsupportedBySolverException, "The selected solver does not support the required format."); std::unique_ptr> solver = linearEquationSolverFactory.create(std::move(bsccEquationSystem)); solver->solveEquations(bsccEquationSystemSolution, bsccEquationSystemRightSide); } @@ -557,6 +560,8 @@ namespace storm { rewardSolution = std::vector(rewardEquationSystemMatrix.getColumnCount(), one); { + // Check whether we have the right input format for the solver. + STORM_LOG_THROW(linearEquationSolverFactory.getEquationProblemFormat() == storm::solver::LinearEquationSolverProblemFormat::EquationSystem, storm::exceptions::FormatUnsupportedBySolverException, "The selected solver does not support the required format."); std::unique_ptr> solver = linearEquationSolverFactory.create(std::move(rewardEquationSystemMatrix)); solver->solveEquations(rewardSolution, rewardRightSide); } @@ -718,58 +723,58 @@ namespace storm { } - template std::vector SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeUntilProbabilities(storm::solver::SolveGoal&& goal, 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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template std::vector SparseCtmcCslHelper::computeNextProbabilities(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeReachabilityTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeReachabilityTimes(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, 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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::storage::SparseMatrix const& probabilityMatrix, std::vector const& stateRewardVector, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, std::vector const& stateRewardVector, std::vector const* exitRateVector, storm::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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template storm::storage::SparseMatrix SparseCtmcCslHelper::computeUniformizedMatrix(storm::storage::SparseMatrix const& rateMatrix, storm::storage::BitVector const& maybeStates, double uniformizationRate, std::vector const& exitRates); template std::vector SparseCtmcCslHelper::computeTransientProbabilities(storm::storage::SparseMatrix const& uniformizedMatrix, std::vector const* addVector, double timeBound, double uniformizationRate, std::vector values, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); #ifdef STORM_HAVE_CARL - template std::vector SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeUntilProbabilities(storm::solver::SolveGoal&& goal, 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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeUntilProbabilities(storm::solver::SolveGoal&& goal, 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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template std::vector SparseCtmcCslHelper::computeNextProbabilities(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template std::vector SparseCtmcCslHelper::computeNextProbabilities(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeReachabilityTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeReachabilityTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeReachabilityTimes(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeReachabilityTimes(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::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::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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, 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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, 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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::storage::SparseMatrix const& probabilityMatrix, std::vector const& stateRewardVector, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::storage::SparseMatrix const& probabilityMatrix, std::vector const& stateRewardVector, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, std::vector const& stateRewardVector, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, std::vector const& stateRewardVector, std::vector const* exitRateVector, storm::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::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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + template std::vector SparseCtmcCslHelper::computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template storm::storage::SparseMatrix SparseCtmcCslHelper::computeProbabilityMatrix(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRates); template storm::storage::SparseMatrix SparseCtmcCslHelper::computeProbabilityMatrix(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRates); diff --git a/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.h b/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.h index 78787b748..cdfc5ca17 100644 --- a/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.h +++ b/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.h @@ -4,6 +4,7 @@ #include "storm/storage/BitVector.h" #include "storm/solver/LinearEquationSolver.h" +#include "storm/solver/SolveGoal.h" #include "storm/utility/NumberTraits.h" @@ -15,43 +16,43 @@ namespace storm { class SparseCtmcCslHelper { public: template ::SupportsExponential, int>::type = 0> - static std::vector computeBoundedUntilProbabilities(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template ::SupportsExponential, int>::type = 0> - static std::vector computeBoundedUntilProbabilities(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& exitRates, bool qualitative, double lowerBound, double upperBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template - 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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeUntilProbabilities(storm::solver::SolveGoal&& goal, 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::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template static std::vector computeNextProbabilities(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template ::SupportsExponential, int>::type = 0> - static std::vector computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template ::SupportsExponential, int>::type = 0> - static std::vector computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template ::SupportsExponential, int>::type = 0> - static std::vector computeCumulativeRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template ::SupportsExponential, int>::type = 0> - static std::vector computeCumulativeRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template - static std::vector computeReachabilityRewards(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template - static std::vector computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeLongRunAverageProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template - static std::vector computeLongRunAverageRewards(storm::storage::SparseMatrix const& probabilityMatrix, RewardModelType const& rewardModel, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, RewardModelType const& rewardModel, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template - static std::vector computeLongRunAverageRewards(storm::storage::SparseMatrix const& probabilityMatrix, std::vector const& stateRewardVector, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, std::vector const& stateRewardVector, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template - static std::vector computeReachabilityTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeReachabilityTimes(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); /*! * Computes the matrix representing the transitions of the uniformized CTMC. @@ -104,7 +105,7 @@ namespace storm { private: template - static std::vector computeLongRunAverages(storm::storage::SparseMatrix const& probabilityMatrix, std::function const& valueGetter, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeLongRunAverages(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& probabilityMatrix, std::function const& valueGetter, std::vector const* exitRateVector, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); }; } } diff --git a/src/storm/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp b/src/storm/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp index 3aaeec73d..4c49a6325 100644 --- a/src/storm/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp +++ b/src/storm/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp @@ -27,6 +27,7 @@ #include "storm/exceptions/InvalidStateException.h" #include "storm/exceptions/InvalidPropertyException.h" #include "storm/exceptions/InvalidOperationException.h" +#include "storm/exceptions/UncheckedRequirementException.h" namespace storm { namespace modelchecker { @@ -86,8 +87,13 @@ namespace storm { } } } - + + // Check for requirements of the solver. + storm::solver::MinMaxLinearEquationSolverRequirements requirements = minMaxLinearEquationSolverFactory.getRequirements(storm::solver::EquationSystemType::UntilProbabilities); + STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Cannot establish requirements for solver."); + std::unique_ptr> solver = minMaxLinearEquationSolverFactory.create(aProbabilistic); + solver->setRequirementsChecked(); solver->setCachingEnabled(true); // Perform the actual value iteration @@ -368,7 +374,13 @@ namespace storm { storm::storage::SparseMatrix sspMatrix = sspMatrixBuilder.build(currentChoice, numberOfSspStates, numberOfSspStates); std::vector x(numberOfSspStates); + + // Check for requirements of the solver. + storm::solver::MinMaxLinearEquationSolverRequirements requirements = minMaxLinearEquationSolverFactory.getRequirements(storm::solver::EquationSystemType::StochasticShortestPath); + STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Cannot establish requirements for solver."); + std::unique_ptr> solver = minMaxLinearEquationSolverFactory.create(sspMatrix); + solver->setRequirementsChecked(); solver->solveEquations(dir, x, b); // Prepare result vector. @@ -570,11 +582,16 @@ namespace storm { std::vector w = v; std::vector x(aProbabilistic.getRowGroupCount(), storm::utility::zero()); std::vector b = probabilisticChoiceRewards; + + // Check for requirements of the solver. + storm::solver::MinMaxLinearEquationSolverRequirements requirements = minMaxLinearEquationSolverFactory.getRequirements(storm::solver::EquationSystemType::ReachabilityRewards); + STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Cannot establish requirements for solver."); + auto solver = minMaxLinearEquationSolverFactory.create(std::move(aProbabilistic)); + solver->setRequirementsChecked(true); solver->setCachingEnabled(true); while (true) { - // Compute the expected total rewards for the probabilistic states solver->solveEquations(dir, x, b); diff --git a/src/storm/modelchecker/hints/ModelCheckerHint.h b/src/storm/modelchecker/hints/ModelCheckerHint.h index 37fc7ec44..afa24484a 100644 --- a/src/storm/modelchecker/hints/ModelCheckerHint.h +++ b/src/storm/modelchecker/hints/ModelCheckerHint.h @@ -7,14 +7,12 @@ namespace storm { template class ExplicitModelCheckerHint; - /*! * This class contains information that might accelerate the model checking process. * @note The model checker has to make sure whether a given hint is actually applicable and thus a hint might be ignored. */ class ModelCheckerHint { public: - ModelCheckerHint() = default; // Returns true iff this hint does not contain any information diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparseMaPcaaWeightVectorChecker.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparseMaPcaaWeightVectorChecker.cpp index 6325a9d66..a7ce425a5 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparseMaPcaaWeightVectorChecker.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparseMaPcaaWeightVectorChecker.cpp @@ -7,7 +7,7 @@ #include "storm/models/sparse/StandardRewardModel.h" #include "storm/utility/macros.h" #include "storm/utility/vector.h" -#include "storm/solver/GmmxxLinearEquationSolver.h" +#include "storm/solver/NativeLinearEquationSolver.h" #include "storm/logic/Formulas.h" #include "storm/exceptions/InvalidOperationException.h" @@ -311,10 +311,9 @@ namespace storm { template ::SupportsExponential, int>::type> std::unique_ptr::LinEqSolverData> SparseMaPcaaWeightVectorChecker::initLinEqSolver(SubModel const& PS) const { std::unique_ptr result(new LinEqSolverData()); - auto factory = std::make_unique>(); + auto factory = std::make_unique>(); // We choose Jacobi since we call the solver very frequently on 'easy' inputs (note that jacobi without preconditioning has very little overhead). - factory->getSettings().setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings::SolutionMethod::Jacobi); - factory->getSettings().setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings::Preconditioner::None); + factory->getSettings().setSolutionMethod(storm::solver::NativeLinearEquationSolverSettings::SolutionMethod::Jacobi); result->factory = std::move(factory); result->b.resize(PS.getNumberOfStates()); return result; diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 9fde067e9..d05c86e1f 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -48,7 +48,7 @@ namespace storm { std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeBoundedUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getNonStrictUpperBound(), *linearEquationSolverFactory, checkTask.getHint()); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeBoundedUntilProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getNonStrictUpperBound(), *linearEquationSolverFactory, checkTask.getHint()); std::unique_ptr result = std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); return result; } @@ -69,7 +69,7 @@ namespace storm { std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory, checkTask.getHint()); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory, checkTask.getHint()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -78,7 +78,7 @@ namespace storm { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -86,7 +86,7 @@ namespace storm { std::unique_ptr SparseDtmcPrctlModelChecker::computeCumulativeRewards(storm::logic::RewardMeasureType, CheckTask const& checkTask) { storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(rewardPathFormula.hasIntegerBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeCumulativeRewards(this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getNonStrictBound(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeCumulativeRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getNonStrictBound(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -94,7 +94,7 @@ namespace storm { std::unique_ptr SparseDtmcPrctlModelChecker::computeInstantaneousRewards(storm::logic::RewardMeasureType, CheckTask const& checkTask) { storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(rewardPathFormula.hasIntegerBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeInstantaneousRewards(this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getBound(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeInstantaneousRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getBound(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -103,7 +103,7 @@ namespace storm { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(eventuallyFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory, checkTask.getHint()); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory, checkTask.getHint()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -112,13 +112,13 @@ namespace storm { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), nullptr, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), nullptr, *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template std::unique_ptr SparseDtmcPrctlModelChecker::computeLongRunAverageRewards(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) { - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageRewards(this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), nullptr, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), nullptr, *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -134,7 +134,7 @@ namespace storm { ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -149,7 +149,7 @@ namespace storm { ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 3b9806ae3..4f59fdd01 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -16,7 +16,7 @@ #include "storm/modelchecker/multiobjective/multiObjectiveModelChecking.h" -#include "storm/solver/LpSolver.h" +#include "storm/solver/SolveGoal.h" #include "storm/settings/modules/GeneralSettings.h" @@ -76,7 +76,7 @@ namespace storm { std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeStepBoundedUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getNonStrictUpperBound(), *minMaxLinearEquationSolverFactory, checkTask.getHint()); + std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeStepBoundedUntilProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getNonStrictUpperBound(), *minMaxLinearEquationSolverFactory, checkTask.getHint()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } } @@ -99,7 +99,7 @@ namespace storm { std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), *minMaxLinearEquationSolverFactory, checkTask.getHint()); + auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), *minMaxLinearEquationSolverFactory, checkTask.getHint()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); @@ -113,7 +113,7 @@ namespace storm { STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *minMaxLinearEquationSolverFactory); + auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(ret))); } @@ -130,7 +130,7 @@ namespace storm { ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - return storm::modelchecker::helper::SparseMdpPrctlHelper::computeConditionalProbabilities(checkTask.getOptimizationDirection(), *this->getModel().getInitialStates().begin(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), *minMaxLinearEquationSolverFactory); + return storm::modelchecker::helper::SparseMdpPrctlHelper::computeConditionalProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), *minMaxLinearEquationSolverFactory); } template @@ -138,7 +138,7 @@ namespace storm { storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(rewardPathFormula.hasIntegerBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeCumulativeRewards(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getNonStrictBound(), *minMaxLinearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeCumulativeRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getNonStrictBound(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -147,7 +147,7 @@ namespace storm { storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(rewardPathFormula.hasIntegerBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeInstantaneousRewards(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getBound(), *minMaxLinearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeInstantaneousRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getBound(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } @@ -157,7 +157,7 @@ namespace storm { STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(eventuallyFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityRewards(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), *minMaxLinearEquationSolverFactory, checkTask.getHint()); + auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), *minMaxLinearEquationSolverFactory, checkTask.getHint()); std::unique_ptr result(new ExplicitQuantitativeCheckResult(std::move(ret.values))); if (checkTask.isProduceSchedulersSet() && ret.scheduler) { result->asExplicitQuantitativeCheckResult().setScheduler(std::move(ret.scheduler)); @@ -171,19 +171,17 @@ namespace storm { STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(stateFormula); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeLongRunAverageProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), *minMaxLinearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template std::unique_ptr SparseMdpPrctlModelChecker::computeLongRunAverageRewards(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) { STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); - std::vector result = storm::modelchecker::helper::SparseMdpPrctlHelper::computeLongRunAverageRewards(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getUniqueRewardModel(), *minMaxLinearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseMdpPrctlHelper::computeLongRunAverageRewards(storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getUniqueRewardModel(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(result))); } - - template std::unique_ptr SparseMdpPrctlModelChecker::checkMultiObjectiveFormula(CheckTask const& checkTask) { return multiobjective::performMultiObjectiveModelChecking(this->getModel(), checkTask.getFormula()); diff --git a/src/storm/modelchecker/prctl/helper/BaierUpperRewardBoundsComputer.cpp b/src/storm/modelchecker/prctl/helper/BaierUpperRewardBoundsComputer.cpp new file mode 100644 index 000000000..1f6eaa8a6 --- /dev/null +++ b/src/storm/modelchecker/prctl/helper/BaierUpperRewardBoundsComputer.cpp @@ -0,0 +1,135 @@ +#include "storm/modelchecker/prctl/helper/BaierUpperRewardBoundsComputer.h" + +#include "storm/adapters/RationalNumberAdapter.h" + +#include "storm/storage/SparseMatrix.h" +#include "storm/storage/BitVector.h" +#include "storm/storage/StronglyConnectedComponentDecomposition.h" + +#include "storm/utility/macros.h" + +namespace storm { + namespace modelchecker { + namespace helper { + + template + BaierUpperRewardBoundsComputer::BaierUpperRewardBoundsComputer(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& rewards, std::vector const& oneStepTargetProbabilities) : transitionMatrix(transitionMatrix), rewards(rewards), oneStepTargetProbabilities(oneStepTargetProbabilities) { + // Intentionally left empty. + } + + template + ValueType BaierUpperRewardBoundsComputer::computeUpperBound() { + std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); + + std::vector stateToScc(transitionMatrix.getRowGroupCount()); + { + // Start with an SCC decomposition of the system. + storm::storage::StronglyConnectedComponentDecomposition sccDecomposition(transitionMatrix); + + uint64_t sccIndex = 0; + for (auto const& block : sccDecomposition) { + for (auto const& state : block) { + stateToScc[state] = sccIndex; + } + ++sccIndex; + } + } + + // The states that we still need to assign a value. + storm::storage::BitVector remainingStates(transitionMatrix.getRowGroupCount(), true); + + // A choice is valid iff it goes to non-remaining states with non-zero probability. + storm::storage::BitVector validChoices(transitionMatrix.getRowCount()); + + // Initially, mark all choices as valid that have non-zero probability to go to the target states directly. + uint64_t index = 0; + for (auto const& e : oneStepTargetProbabilities) { + if (!storm::utility::isZero(e)) { + validChoices.set(index); + } + ++index; + } + + // Vector that holds the result. + std::vector result(transitionMatrix.getRowGroupCount()); + + // Process all states as long as there are remaining ones. + std::vector newStates; + while (!remainingStates.empty()) { + for (auto state : remainingStates) { + bool allChoicesValid = true; + for (auto row = transitionMatrix.getRowGroupIndices()[state], endRow = transitionMatrix.getRowGroupIndices()[state + 1]; row < endRow; ++row) { + if (validChoices.get(row)) { + continue; + } + + bool choiceValid = false; + for (auto const& entry : transitionMatrix.getRow(row)) { + if (storm::utility::isZero(entry.getValue())) { + continue; + } + + if (!remainingStates.get(entry.getColumn())) { + choiceValid = true; + break; + } + } + + if (choiceValid) { + validChoices.set(row); + } else { + allChoicesValid = false; + } + } + + if (allChoicesValid) { + newStates.push_back(state); + } + } + + // Compute d_t over the newly found states. + for (auto state : newStates) { + result[state] = storm::utility::one(); + for (auto row = transitionMatrix.getRowGroupIndices()[state], endRow = transitionMatrix.getRowGroupIndices()[state + 1]; row < endRow; ++row) { + ValueType rowValue = oneStepTargetProbabilities[row]; + for (auto const& entry : transitionMatrix.getRow(row)) { + if (!remainingStates.get(entry.getColumn())) { + rowValue += entry.getValue() * (stateToScc[state] == stateToScc[entry.getColumn()] ? result[entry.getColumn()] : storm::utility::one()); + } + } + STORM_LOG_ASSERT(rowValue > storm::utility::zero(), "Expected entry with value greater 0."); + result[state] = std::min(result[state], rowValue); + } + } + + remainingStates.set(newStates.begin(), newStates.end(), false); + newStates.clear(); + } + + for (uint64_t state = 0; state < result.size(); ++state) { + ValueType maxReward = storm::utility::zero(); + for (auto row = transitionMatrix.getRowGroupIndices()[state], endRow = transitionMatrix.getRowGroupIndices()[state + 1]; row < endRow; ++row) { + maxReward = std::max(maxReward, rewards[row]); + } + result[state] = storm::utility::one() / result[state] * maxReward; + } + + ValueType upperBound = storm::utility::zero(); + for (auto const& e : result) { + upperBound += e; + } + + STORM_LOG_TRACE("Baier algorithm for reward bound computation (variant 2) computed bound " << upperBound << "."); + std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); + STORM_LOG_TRACE("Computed upper bounds on rewards in " << std::chrono::duration_cast(end - start).count() << "ms."); + return upperBound; + } + + template class BaierUpperRewardBoundsComputer; + +#ifdef STORM_HAVE_CARL + template class BaierUpperRewardBoundsComputer; +#endif + } + } +} diff --git a/src/storm/modelchecker/prctl/helper/BaierUpperRewardBoundsComputer.h b/src/storm/modelchecker/prctl/helper/BaierUpperRewardBoundsComputer.h new file mode 100644 index 000000000..a9b343d2e --- /dev/null +++ b/src/storm/modelchecker/prctl/helper/BaierUpperRewardBoundsComputer.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +namespace storm { + namespace storage { + template + class SparseMatrix; + } + + namespace modelchecker { + namespace helper { + + template + class BaierUpperRewardBoundsComputer { + public: + /*! + * Creates an object that can compute upper bounds on the *maximal* expected rewards for the provided MDP. + * + * @param transitionMatrix The matrix defining the transitions of the system without the transitions + * that lead directly to the goal state. + * @param rewards The rewards of each choice. + * @param oneStepTargetProbabilities For each choice the probability to go to a goal state in one step. + */ + BaierUpperRewardBoundsComputer(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& rewards, std::vector const& oneStepTargetProbabilities); + + /*! + * Computes an upper bound on the expected rewards. + */ + ValueType computeUpperBound(); + + private: + storm::storage::SparseMatrix const& transitionMatrix; + std::vector const& rewards; + std::vector const& oneStepTargetProbabilities; + }; + } + } +} diff --git a/src/storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.cpp b/src/storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.cpp new file mode 100644 index 000000000..f3789d31b --- /dev/null +++ b/src/storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.cpp @@ -0,0 +1,302 @@ +#include "storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.h" + +#include "storm-config.h" + +#include "storm/storage/BitVector.h" +#include "storm/storage/ConsecutiveUint64DynamicPriorityQueue.h" +#include "storm/storage/SparseMatrix.h" + +#include "storm/storage/sparse/StateType.h" + +#include "storm/utility/macros.h" +#include "storm/utility/constants.h" +#include "storm/utility/ConstantsComparator.h" + +namespace storm { + namespace modelchecker { + namespace helper { + + template + DsMpiDtmcUpperRewardBoundsComputer::DsMpiDtmcUpperRewardBoundsComputer(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& rewards, std::vector const& oneStepTargetProbabilities) : transitionMatrix(transitionMatrix), originalRewards(rewards), originalOneStepTargetProbabilities(oneStepTargetProbabilities), backwardTransitions(transitionMatrix.transpose()), p(transitionMatrix.getRowGroupCount()), w(transitionMatrix.getRowGroupCount()), rewards(rewards), targetProbabilities(oneStepTargetProbabilities) { + // Intentionally left empty. + } + + template + std::vector DsMpiDtmcUpperRewardBoundsComputer::computeUpperBounds() { + std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); + sweep(); + ValueType lambda = computeLambda(); + STORM_LOG_TRACE("DS-MPI computed lambda as " << lambda << "."); + + // Finally compute the upper bounds for the states. + std::vector result(transitionMatrix.getRowGroupCount()); + auto one = storm::utility::one(); + for (storm::storage::sparse::state_type state = 0; state < result.size(); ++state) { + result[state] = w[state] + (one - p[state]) * lambda; + } + +#ifndef NDEBUG + ValueType max = storm::utility::zero(); + uint64_t nonZeroCount = 0; + for (auto const& e : result) { + if (!storm::utility::isZero(e)) { + ++nonZeroCount; + max = std::max(max, e); + } + } + STORM_LOG_TRACE("DS-MPI computed " << nonZeroCount << " non-zero upper bounds and a maximal bound of " << max << "."); +#endif + std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); + STORM_LOG_TRACE("Computed upper bounds on rewards in " << std::chrono::duration_cast(end - start).count() << "ms."); + return result; + } + + template + ValueType DsMpiDtmcUpperRewardBoundsComputer::computeLambda() const { + ValueType lambda = storm::utility::zero(); + for (storm::storage::sparse::state_type state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + lambda = std::max(lambda, computeLambdaForChoice(state)); + } + return lambda; + } + + template + ValueType DsMpiDtmcUpperRewardBoundsComputer::computeLambdaForChoice(uint64_t choice) const { + ValueType localLambda = storm::utility::zero(); + uint64_t state = this->getStateForChoice(choice); + + // Check whether condition (I) or (II) applies. + ValueType probSum = originalOneStepTargetProbabilities[choice]; + for (auto const& e : transitionMatrix.getRow(choice)) { + probSum += e.getValue() * p[e.getColumn()]; + } + + if (p[state] < probSum) { + STORM_LOG_TRACE("Condition (I) does apply for state " << state << " as " << p[state] << " < " << probSum << "."); + // Condition (I) applies. + localLambda = probSum - p[state]; + ValueType nominator = originalRewards[choice]; + for (auto const& e : transitionMatrix.getRow(choice)) { + nominator += e.getValue() * w[e.getColumn()]; + } + nominator -= w[state]; + localLambda = nominator / localLambda; + } else { + STORM_LOG_TRACE("Condition (I) does not apply for state " << state << std::setprecision(30) << " as " << probSum << " <= " << p[state] << "."); + // Here, condition (II) automatically applies and as the resulting local lambda is 0, we + // don't need to consider it. + +#ifndef NDEBUG + // Actually check condition (II). + ValueType rewardSum = originalRewards[choice]; + for (auto const& e : transitionMatrix.getRow(choice)) { + rewardSum += e.getValue() * w[e.getColumn()]; + } + STORM_LOG_WARN_COND(w[state] >= rewardSum || storm::utility::ConstantsComparator().isEqual(w[state], rewardSum), "Expected condition (II) to hold in state " << state << ", but " << w[state] << " < " << rewardSum << "."); + STORM_LOG_WARN_COND(storm::utility::ConstantsComparator().isEqual(probSum, p[state]), "Expected condition (II) to hold in state " << state << ", but " << probSum << " != " << p[state] << "."); +#endif + } + + return localLambda; + } + + template + uint64_t DsMpiDtmcUpperRewardBoundsComputer::getStateForChoice(uint64_t choice) const { + return choice; + } + + template + class DsMpiDtmcPriorityLess { + public: + DsMpiDtmcPriorityLess(DsMpiDtmcUpperRewardBoundsComputer const& dsmpi) : dsmpi(dsmpi) { + // Intentionally left empty. + } + + bool operator()(storm::storage::sparse::state_type const& a, storm::storage::sparse::state_type const& b) { + ValueType pa = dsmpi.targetProbabilities[a]; + ValueType pb = dsmpi.targetProbabilities[b]; + if (pa < pb) { + return true; + } else if (pa == pb) { + return dsmpi.rewards[a] > dsmpi.rewards[b]; + } + return false; + } + + private: + DsMpiDtmcUpperRewardBoundsComputer const& dsmpi; + }; + + template + void DsMpiDtmcUpperRewardBoundsComputer::sweep() { + // Create a priority queue that allows for easy retrieval of the currently best state. + storm::storage::ConsecutiveUint64DynamicPriorityQueue> queue(transitionMatrix.getRowCount(), DsMpiDtmcPriorityLess(*this)); + + // Keep track of visited states. + storm::storage::BitVector visited(p.size()); + + while (!queue.empty()) { + // Get first entry in queue. + storm::storage::sparse::state_type currentState = queue.popTop(); + + // Mark state as visited. + visited.set(currentState); + + // Set weight and probability for the state. + w[currentState] = rewards[currentState]; + p[currentState] = targetProbabilities[currentState]; + + for (auto const& e : backwardTransitions.getRow(currentState)) { + if (visited.get(e.getColumn())) { + continue; + } + + // Update reward/probability values. + rewards[e.getColumn()] += e.getValue() * w[currentState]; + targetProbabilities[e.getColumn()] += e.getValue() * p[currentState]; + + // Increase priority of element. + queue.increase(e.getColumn()); + } + } + } + + template + DsMpiMdpUpperRewardBoundsComputer::DsMpiMdpUpperRewardBoundsComputer(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& rewards, std::vector const& oneStepTargetProbabilities) : DsMpiDtmcUpperRewardBoundsComputer(transitionMatrix, rewards, oneStepTargetProbabilities), policy(transitionMatrix.getRowCount()) { + + // Create a mapping from choices to states. + // Also pick a choice in each state that maximizes the target probability and minimizes the reward. + choiceToState.resize(transitionMatrix.getRowCount()); + for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { + uint64_t choice = transitionMatrix.getRowGroupIndices()[state]; + + boost::optional minReward; + ValueType maxProb = storm::utility::zero(); + + for (uint64_t row = choice, endRow = transitionMatrix.getRowGroupIndices()[state + 1]; row < endRow; ++row) { + choiceToState[row] = state; + + if (this->targetProbabilities[row] > maxProb) { + maxProb = this->targetProbabilities[row]; + minReward = this->rewards[row]; + choice = row; + } else if (this->targetProbabilities[row] == maxProb && (!minReward || minReward.get() > this->rewards[row])) { + minReward = this->rewards[row]; + choice = row; + } + } + + setChoiceInState(state, choice); + } + } + + template + ValueType DsMpiMdpUpperRewardBoundsComputer::computeLambda() const { + ValueType lambda = storm::utility::zero(); + for (storm::storage::sparse::state_type state = 0; state < this->transitionMatrix.getRowGroupCount(); ++state) { + lambda = std::max(lambda, this->computeLambdaForChoice(this->getChoiceInState(state))); + } + return lambda; + } + + template + uint64_t DsMpiMdpUpperRewardBoundsComputer::getStateForChoice(uint64_t choice) const { + return choiceToState[choice]; + } + + template + class DsMpiMdpPriorityLess { + public: + DsMpiMdpPriorityLess(DsMpiMdpUpperRewardBoundsComputer const& dsmpi) : dsmpi(dsmpi) { + // Intentionally left empty. + } + + bool operator()(storm::storage::sparse::state_type const& a, storm::storage::sparse::state_type const& b) { + uint64_t choiceA = dsmpi.getChoiceInState(a); + uint64_t choiceB = dsmpi.getChoiceInState(b); + + ValueType pa = dsmpi.targetProbabilities[choiceA]; + ValueType pb = dsmpi.targetProbabilities[choiceB]; + if (pa < pb) { + return true; + } else if (pa == pb) { + return dsmpi.rewards[choiceB] > dsmpi.rewards[choiceB]; + } + return false; + } + + private: + DsMpiMdpUpperRewardBoundsComputer const& dsmpi; + }; + + template + void DsMpiMdpUpperRewardBoundsComputer::sweep() { + // Create a priority queue that allows for easy retrieval of the currently best state. + storm::storage::ConsecutiveUint64DynamicPriorityQueue> queue(this->transitionMatrix.getRowGroupCount(), DsMpiMdpPriorityLess(*this)); + + // Keep track of visited states. + storm::storage::BitVector visited(this->transitionMatrix.getRowGroupCount()); + + while (!queue.empty()) { + // Get first entry in queue. + storm::storage::sparse::state_type currentState = queue.popTop(); + + // Mark state as visited. + visited.set(currentState); + + // Set weight and probability for the state. + uint64_t choiceInCurrentState = this->getChoiceInState(currentState); + this->w[currentState] = this->rewards[choiceInCurrentState]; + this->p[currentState] = this->targetProbabilities[choiceInCurrentState]; + + for (auto const& choiceEntry : this->backwardTransitions.getRow(currentState)) { + uint64_t predecessor = this->getStateForChoice(choiceEntry.getColumn()); + if (visited.get(predecessor)) { + continue; + } + + // Update reward/probability values. + this->rewards[choiceEntry.getColumn()] += choiceEntry.getValue() * this->w[currentState]; + this->targetProbabilities[choiceEntry.getColumn()] += choiceEntry.getValue() * this->p[currentState]; + + // If the choice is not the one that is currently taken in the predecessor state, we might need + // to update it. + uint64_t currentChoiceInPredecessor = this->getChoiceInState(predecessor); + if (currentChoiceInPredecessor != choiceEntry.getColumn()) { + // Check whether the updates choice now becomes a better choice in the predecessor state. + ValueType const& newTargetProbability = this->targetProbabilities[choiceEntry.getColumn()]; + ValueType const& newReward = this->rewards[choiceEntry.getColumn()]; + ValueType const& currentTargetProbability = this->targetProbabilities[this->getChoiceInState(predecessor)]; + ValueType const& currentReward = this->rewards[this->getChoiceInState(predecessor)]; + + if (newTargetProbability > currentTargetProbability || (newTargetProbability == currentTargetProbability && newReward < currentReward)) { + setChoiceInState(predecessor, choiceEntry.getColumn()); + } + } + + // Notify the priority of a potential increase of the priority of the element. + queue.increase(predecessor); + } + } + } + + template + uint64_t DsMpiMdpUpperRewardBoundsComputer::getChoiceInState(uint64_t state) const { + return policy[state]; + } + + template + void DsMpiMdpUpperRewardBoundsComputer::setChoiceInState(uint64_t state, uint64_t choice) { + policy[state] = choice; + } + + template class DsMpiDtmcUpperRewardBoundsComputer; + template class DsMpiMdpUpperRewardBoundsComputer; + +#ifdef STORM_HAVE_CARL + template class DsMpiDtmcUpperRewardBoundsComputer; + template class DsMpiMdpUpperRewardBoundsComputer; +#endif + } + } +} diff --git a/src/storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.h b/src/storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.h new file mode 100644 index 000000000..7f2bb4278 --- /dev/null +++ b/src/storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.h @@ -0,0 +1,104 @@ +#pragma once + +#include +#include + +namespace storm { + namespace storage { + template + class SparseMatrix; + } + + namespace modelchecker { + namespace helper { + + template + class DsMpiDtmcPriorityLess; + + template + class DsMpiDtmcUpperRewardBoundsComputer { + public: + /*! + * Creates an object that can compute upper bounds on the expected rewards for the provided DTMC. + * + * @param transitionMatrix The matrix defining the transitions of the system without the transitions + * that lead directly to the goal state. + * @param rewards The rewards of each state. + * @param oneStepTargetProbabilities For each state the probability to go to a goal state in one step. + */ + DsMpiDtmcUpperRewardBoundsComputer(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& rewards, std::vector const& oneStepTargetProbabilities); + + /*! + * Computes upper bounds on the expected rewards. + */ + std::vector computeUpperBounds(); + + protected: + /*! + * Performs a Dijkstra sweep. + */ + virtual void sweep(); + + /*! + * Computes the lambda used for the estimation. + */ + virtual ValueType computeLambda() const; + + /*! + * Computes the lambda just for the provided choice. + */ + ValueType computeLambdaForChoice(uint64_t choice) const; + + /*! + * Retrieves the state associated with the given choice. + */ + virtual uint64_t getStateForChoice(uint64_t choice) const; + + // References to input data. + storm::storage::SparseMatrix const& transitionMatrix; + std::vector const& originalRewards; + std::vector const& originalOneStepTargetProbabilities; + + // Derived from input data. + storm::storage::SparseMatrix backwardTransitions; + + // Data that the algorithm uses internally. + std::vector p; + std::vector w; + std::vector rewards; + std::vector targetProbabilities; + + friend class DsMpiDtmcPriorityLess; + }; + + template + class DsMpiMdpPriorityLess; + + template + class DsMpiMdpUpperRewardBoundsComputer : public DsMpiDtmcUpperRewardBoundsComputer { + public: + /*! + * Creates an object that can compute upper bounds on the *minimal* expected rewards for the provided MDP. + * + * @param transitionMatrix The matrix defining the transitions of the system without the transitions + * that lead directly to the goal state. + * @param rewards The rewards of each choice. + * @param oneStepTargetProbabilities For each choice the probability to go to a goal state in one step. + */ + DsMpiMdpUpperRewardBoundsComputer(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& rewards, std::vector const& oneStepTargetProbabilities); + + private: + virtual void sweep() override; + virtual ValueType computeLambda() const override; + virtual uint64_t getStateForChoice(uint64_t choice) const override; + uint64_t getChoiceInState(uint64_t state) const; + void setChoiceInState(uint64_t state, uint64_t choice); + + std::vector choiceToState; + std::vector policy; + + friend class DsMpiMdpPriorityLess; + }; + } + } +} diff --git a/src/storm/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp index 3daaee646..d7986e56d 100644 --- a/src/storm/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp @@ -31,10 +31,7 @@ namespace storm { std::pair, storm::dd::Bdd> statesWithProbability01 = storm::utility::graph::performProb01(model, transitionMatrix, phiStates, psiStates); storm::dd::Bdd maybeStates = !statesWithProbability01.first && !statesWithProbability01.second && model.getReachableStates(); - // Perform some logging. - STORM_LOG_INFO("Found " << statesWithProbability01.first.getNonZeroCount() << " 'no' states."); - STORM_LOG_INFO("Found " << statesWithProbability01.second.getNonZeroCount() << " 'yes' states."); - STORM_LOG_INFO("Found " << maybeStates.getNonZeroCount() << " 'maybe' states."); + STORM_LOG_INFO("Preprocessing: " << statesWithProbability01.first.getNonZeroCount() << " states with probability 1, " << statesWithProbability01.second.getNonZeroCount() << " with probability 0 (" << maybeStates.getNonZeroCount() << " states remaining)."); // Check whether we need to compute exact probabilities for some states. if (qualitative) { @@ -59,11 +56,16 @@ namespace storm { prob1StatesAsColumn = prob1StatesAsColumn.swapVariables(model.getRowColumnMetaVariablePairs()); storm::dd::Add subvector = submatrix * prob1StatesAsColumn; subvector = subvector.sumAbstract(model.getColumnVariables()); + + // Check whether we need to create an equation system. + bool convertToEquationSystem = linearEquationSolverFactory.getEquationProblemFormat() == storm::solver::LinearEquationSolverProblemFormat::EquationSystem; - // Finally cut away all columns targeting non-maybe states and convert the matrix into the matrix needed - // for solving the equation system (i.e. compute (I-A)). + // Finally cut away all columns targeting non-maybe states and potentially convert the matrix + // into the matrix needed for solving the equation system (i.e. compute (I-A)). submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); - submatrix = (model.getRowColumnIdentity() * maybeStatesAdd) - submatrix; + if (convertToEquationSystem) { + submatrix = (model.getRowColumnIdentity() * maybeStatesAdd) - submatrix; + } // Create the solution vector. std::vector x(maybeStates.getNonZeroCount(), storm::utility::convertNumber(0.5)); @@ -104,6 +106,8 @@ namespace storm { storm::dd::Bdd statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0(model, transitionMatrix.notZero(), phiStates, psiStates, stepBound); storm::dd::Bdd maybeStates = statesWithProbabilityGreater0 && !psiStates && model.getReachableStates(); + STORM_LOG_INFO("Preprocessing: " << statesWithProbabilityGreater0.getNonZeroCount() << " states with probability greater 0."); + // If there are maybe states, we need to perform matrix-vector multiplications. if (!maybeStates.isZero()) { // Create the ODD for the translation between symbolic and explicit storage. @@ -199,9 +203,8 @@ namespace storm { storm::dd::Bdd infinityStates = storm::utility::graph::performProb1(model, transitionMatrix.notZero(), model.getReachableStates(), targetStates); infinityStates = !infinityStates && model.getReachableStates(); storm::dd::Bdd maybeStates = (!targetStates && !infinityStates) && model.getReachableStates(); - STORM_LOG_INFO("Found " << infinityStates.getNonZeroCount() << " 'infinity' states."); - STORM_LOG_INFO("Found " << targetStates.getNonZeroCount() << " 'target' states."); - STORM_LOG_INFO("Found " << maybeStates.getNonZeroCount() << " 'maybe' states."); + + STORM_LOG_INFO("Preprocessing: " << infinityStates.getNonZeroCount() << " states with reward infinity, " << targetStates.getNonZeroCount() << " target states (" << maybeStates.getNonZeroCount() << " states remaining)."); // Check whether we need to compute exact rewards for some states. if (qualitative) { @@ -224,10 +227,15 @@ namespace storm { // Then compute the state reward vector to use in the computation. storm::dd::Add subvector = rewardModel.getTotalRewardVector(maybeStatesAdd, submatrix, model.getColumnVariables()); - // Finally cut away all columns targeting non-maybe states and convert the matrix into the matrix needed - // for solving the equation system (i.e. compute (I-A)). + // Check whether we need to create an equation system. + bool convertToEquationSystem = linearEquationSolverFactory.getEquationProblemFormat() == storm::solver::LinearEquationSolverProblemFormat::EquationSystem; + + // Finally cut away all columns targeting non-maybe states and potentially convert the matrix + // into the matrix needed for solving the equation system (i.e. compute (I-A)). submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); - submatrix = (model.getRowColumnIdentity() * maybeStatesAdd) - submatrix; + if (convertToEquationSystem) { + submatrix = (model.getRowColumnIdentity() * maybeStatesAdd) - submatrix; + } // Create the solution vector. std::vector x(maybeStates.getNonZeroCount(), storm::utility::convertNumber(0.5)); @@ -255,7 +263,7 @@ namespace storm { storm::dd::Odd odd = model.getReachableStates().createOdd(); storm::storage::SparseMatrix explicitProbabilityMatrix = model.getTransitionMatrix().toMatrix(odd, odd); - std::vector result = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeLongRunAverageProbabilities(explicitProbabilityMatrix, targetStates.toVector(odd), linearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal(), explicitProbabilityMatrix, targetStates.toVector(odd), linearEquationSolverFactory); return std::unique_ptr(new HybridQuantitativeCheckResult(model.getReachableStates(), model.getManager().getBddZero(), model.getManager().template getAddZero(), model.getReachableStates(), std::move(odd), std::move(result))); } @@ -265,7 +273,7 @@ namespace storm { storm::dd::Odd odd = model.getReachableStates().createOdd(); storm::storage::SparseMatrix explicitProbabilityMatrix = model.getTransitionMatrix().toMatrix(odd, odd); - std::vector result = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeLongRunAverageRewards(explicitProbabilityMatrix, rewardModel.getTotalRewardVector(model.getTransitionMatrix(), model.getColumnVariables()).toVector(odd), linearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeLongRunAverageRewards(storm::solver::SolveGoal(), explicitProbabilityMatrix, rewardModel.getTotalRewardVector(model.getTransitionMatrix(), model.getColumnVariables()).toVector(odd), linearEquationSolverFactory); return std::unique_ptr(new HybridQuantitativeCheckResult(model.getReachableStates(), model.getManager().getBddZero(), model.getManager().template getAddZero(), model.getReachableStates(), std::move(odd), std::move(result))); } diff --git a/src/storm/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp index b0363cd4e..d6b41030a 100644 --- a/src/storm/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp @@ -19,11 +19,43 @@ #include "storm/solver/MinMaxLinearEquationSolver.h" #include "storm/exceptions/InvalidPropertyException.h" +#include "storm/exceptions/UncheckedRequirementException.h" namespace storm { namespace modelchecker { namespace helper { + template + std::vector computeValidInitialSchedulerForUntilProbabilities(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& b) { + uint64_t numberOfMaybeStates = transitionMatrix.getRowGroupCount(); + std::vector result(numberOfMaybeStates); + storm::storage::BitVector targetStates(numberOfMaybeStates); + + for (uint64_t state = 0; state < numberOfMaybeStates; ++state) { + // Record all states with non-zero probability of moving directly to the target states. + for (uint64_t row = transitionMatrix.getRowGroupIndices()[state]; row < transitionMatrix.getRowGroupIndices()[state + 1]; ++row) { + if (!storm::utility::isZero(b[row])) { + targetStates.set(state); + result[state] = row - transitionMatrix.getRowGroupIndices()[state]; + } + } + } + + if (!targetStates.full()) { + storm::storage::Scheduler validScheduler(numberOfMaybeStates); + storm::storage::SparseMatrix backwardTransitions = transitionMatrix.transpose(true); + storm::utility::graph::computeSchedulerProbGreater0E(transitionMatrix, backwardTransitions, storm::storage::BitVector(numberOfMaybeStates, true), targetStates, validScheduler, boost::none); + + for (uint64_t state = 0; state < numberOfMaybeStates; ++state) { + if (!targetStates.get(state)) { + result[state] = validScheduler.getChoice(state).getDeterministicChoice(); + } + } + } + + return result; + } + template std::unique_ptr HybridMdpPrctlHelper::computeUntilProbabilities(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& phiStates, storm::dd::Bdd const& psiStates, bool qualitative, storm::solver::MinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { // We need to identify the states which have to be taken out of the matrix, i.e. all states that have @@ -36,11 +68,8 @@ namespace storm { } storm::dd::Bdd maybeStates = !statesWithProbability01.first && !statesWithProbability01.second && model.getReachableStates(); - // Perform some logging. - STORM_LOG_INFO("Found " << statesWithProbability01.first.getNonZeroCount() << " 'no' states."); - STORM_LOG_INFO("Found " << statesWithProbability01.second.getNonZeroCount() << " 'yes' states."); - STORM_LOG_INFO("Found " << maybeStates.getNonZeroCount() << " 'maybe' states."); - + STORM_LOG_INFO("Preprocessing: " << statesWithProbability01.first.getNonZeroCount() << " states with probability 1, " << statesWithProbability01.second.getNonZeroCount() << " with probability 0 (" << maybeStates.getNonZeroCount() << " states remaining)."); + // Check whether we need to compute exact probabilities for some states. if (qualitative) { // Set the values for all maybe-states to 0.5 to indicate that their probability values are neither 0 nor 1. @@ -71,13 +100,31 @@ namespace storm { // Finally cut away all columns targeting non-maybe states. submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); - // Create the solution vector. - std::vector x(maybeStates.getNonZeroCount(), storm::utility::zero()); - // Translate the symbolic matrix/vector to their explicit representations and solve the equation system. std::pair, std::vector> explicitRepresentation = submatrix.toMatrixVector(subvector, std::move(rowGroupSizes), model.getNondeterminismVariables(), odd, odd); + // Create the solution vector. + std::vector x(explicitRepresentation.first.getRowGroupCount(), storm::utility::zero()); + + // Check for requirements of the solver. + storm::solver::MinMaxLinearEquationSolverRequirements requirements = linearEquationSolverFactory.getRequirements(storm::solver::EquationSystemType::UntilProbabilities, dir); + boost::optional> initialScheduler; + if (!requirements.empty()) { + if (requirements.requires(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler)) { + STORM_LOG_DEBUG("Computing valid scheduler hint, because the solver requires it."); + initialScheduler = computeValidInitialSchedulerForUntilProbabilities(explicitRepresentation.first, explicitRepresentation.second); + + requirements.clearValidInitialScheduler(); + } + STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Cannot establish requirements for solver."); + } + std::unique_ptr> solver = linearEquationSolverFactory.create(std::move(explicitRepresentation.first)); + if (initialScheduler) { + solver->setInitialScheduler(std::move(initialScheduler.get())); + } + solver->setBounds(storm::utility::zero(), storm::utility::one()); + solver->setRequirementsChecked(); solver->solveEquations(dir, x, explicitRepresentation.second); // Return a hybrid check result that stores the numerical values explicitly. @@ -112,6 +159,8 @@ namespace storm { } storm::dd::Bdd maybeStates = statesWithProbabilityGreater0 && !psiStates && model.getReachableStates(); + STORM_LOG_INFO("Preprocessing: " << statesWithProbabilityGreater0.getNonZeroCount() << " states with probability greater 0."); + // If there are maybe states, we need to perform matrix-vector multiplications. if (!maybeStates.isZero()) { // Create the ODD for the translation between symbolic and explicit storage. @@ -202,6 +251,76 @@ namespace storm { return std::unique_ptr(new HybridQuantitativeCheckResult(model.getReachableStates(), model.getManager().getBddZero(), model.getManager().template getAddZero(), model.getReachableStates(), odd, x)); } + template + storm::storage::BitVector computeTargetStatesForReachabilityRewardsFromExplicitRepresentation(storm::storage::SparseMatrix const& transitionMatrix) { + storm::storage::BitVector targetStates(transitionMatrix.getRowGroupCount()); + + // A state is a target state if its row group is empty. + for (uint64_t rowGroup = 0; rowGroup < transitionMatrix.getRowGroupCount(); ++rowGroup) { + if (transitionMatrix.getRowGroupIndices()[rowGroup] == transitionMatrix.getRowGroupIndices()[rowGroup + 1]) { + targetStates.set(rowGroup); + } + } + + return targetStates; + } + + template + std::vector computeValidInitialSchedulerForReachabilityRewards(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& properMaybeStates, storm::storage::BitVector const& targetStates) { + uint64_t numberOfMaybeStates = transitionMatrix.getRowGroupCount(); + std::vector result(numberOfMaybeStates); + + storm::storage::Scheduler validScheduler(numberOfMaybeStates); + storm::storage::SparseMatrix backwardTransitions = transitionMatrix.transpose(true); + storm::utility::graph::computeSchedulerProb1E(storm::storage::BitVector(numberOfMaybeStates, true), transitionMatrix, backwardTransitions, properMaybeStates, targetStates, validScheduler); + + for (uint64_t state = 0; state < numberOfMaybeStates; ++state) { + if (!targetStates.get(state)) { + result[state] = validScheduler.getChoice(state).getDeterministicChoice(); + } + } + + return result; + } + + template + void eliminateTargetStatesFromExplicitRepresentation(std::pair, std::vector>& explicitRepresentation, std::vector& scheduler, storm::storage::BitVector const& properMaybeStates) { + // Eliminate the superfluous entries from the rhs vector and the scheduler. + uint64_t position = 0; + for (auto state : properMaybeStates) { + for (uint64_t row = explicitRepresentation.first.getRowGroupIndices()[state]; row < explicitRepresentation.first.getRowGroupIndices()[state + 1]; ++row) { + explicitRepresentation.second[position] = explicitRepresentation.second[row]; + position++; + } + } + explicitRepresentation.second.resize(position); + explicitRepresentation.second.shrink_to_fit(); + + position = 0; + for (auto state : properMaybeStates) { + scheduler[position] = scheduler[state]; + position++; + } + scheduler.resize(properMaybeStates.getNumberOfSetBits()); + scheduler.shrink_to_fit(); + + // Treat the matrix. + explicitRepresentation.first = explicitRepresentation.first.getSubmatrix(true, properMaybeStates, properMaybeStates); + } + + template + std::vector insertTargetStateValuesIntoExplicitRepresentation(std::vector const& x, storm::storage::BitVector const& properMaybeStates) { + std::vector expandedResult(properMaybeStates.size(), storm::utility::zero()); + + uint64_t position = 0; + for (auto state : properMaybeStates) { + expandedResult[state] = x[position]; + position++; + } + + return expandedResult; + } + template std::unique_ptr HybridMdpPrctlHelper::computeReachabilityRewards(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, storm::dd::Bdd const& targetStates, bool qualitative, storm::solver::MinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { @@ -212,17 +331,16 @@ namespace storm { storm::dd::Bdd infinityStates; storm::dd::Bdd transitionMatrixBdd = transitionMatrix.notZero(); if (dir == OptimizationDirection::Minimize) { - STORM_LOG_WARN("Results of reward computation may be too low, because of zero-reward loops."); infinityStates = storm::utility::graph::performProb1E(model, transitionMatrixBdd, model.getReachableStates(), targetStates, storm::utility::graph::performProbGreater0E(model, transitionMatrixBdd, model.getReachableStates(), targetStates)); } else { infinityStates = storm::utility::graph::performProb1A(model, transitionMatrixBdd, targetStates, storm::utility::graph::performProbGreater0A(model, transitionMatrixBdd, model.getReachableStates(), targetStates)); } infinityStates = !infinityStates && model.getReachableStates(); - storm::dd::Bdd maybeStates = (!targetStates && !infinityStates) && model.getReachableStates(); - STORM_LOG_INFO("Found " << infinityStates.getNonZeroCount() << " 'infinity' states."); - STORM_LOG_INFO("Found " << targetStates.getNonZeroCount() << " 'target' states."); - STORM_LOG_INFO("Found " << maybeStates.getNonZeroCount() << " 'maybe' states."); - + storm::dd::Bdd maybeStatesWithTargetStates = !infinityStates && model.getReachableStates(); + storm::dd::Bdd maybeStates = !targetStates && maybeStatesWithTargetStates; + + STORM_LOG_INFO("Preprocessing: " << infinityStates.getNonZeroCount() << " states with reward infinity, " << targetStates.getNonZeroCount() << " target states (" << maybeStates.getNonZeroCount() << " states remaining)."); + // Check whether we need to compute exact rewards for some states. if (qualitative) { // Set the values for all maybe-states to 1 to indicate that their reward values @@ -231,46 +349,85 @@ namespace storm { } else { // If there are maybe states, we need to solve an equation system. if (!maybeStates.isZero()) { + // Check for requirements of the solver this early so we can adapt the maybe states accordingly. + storm::solver::MinMaxLinearEquationSolverRequirements requirements = linearEquationSolverFactory.getRequirements(storm::solver::EquationSystemType::ReachabilityRewards, dir); + bool requireInitialScheduler = false; + if (!requirements.empty()) { + if (requirements.requires(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler)) { + STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it."); + requireInitialScheduler = true; + requirements.clearValidInitialScheduler(); + } + STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Cannot establish requirements for solver."); + } + + // Compute the set of maybe states that we are required to keep in the translation to explicit. + storm::dd::Bdd requiredMaybeStates = requireInitialScheduler ? maybeStatesWithTargetStates : maybeStates; + // Create the ODD for the translation between symbolic and explicit storage. - storm::dd::Odd odd = maybeStates.createOdd(); + storm::dd::Odd odd = requiredMaybeStates.createOdd(); // Create the matrix and the vector for the equation system. storm::dd::Add maybeStatesAdd = maybeStates.template toAdd(); - // Start by cutting away all rows that do not belong to maybe states. Note that this leaves columns targeting - // non-maybe states in the matrix. - storm::dd::Add submatrix = transitionMatrix * maybeStatesAdd; + // Start by getting rid of + // (a) transitions from non-maybe states, and + // (b) the choices in the transition matrix that lead to a state that is neither a maybe state + // nor a target state ('infinity choices'). + storm::dd::Add choiceFilterAdd = (transitionMatrixBdd && maybeStatesWithTargetStates.renameVariables(model.getRowVariables(), model.getColumnVariables())).existsAbstract(model.getColumnVariables()).template toAdd(); + storm::dd::Add submatrix = transitionMatrix * maybeStatesAdd * choiceFilterAdd; - // Then compute the state reward vector to use in the computation. + // Then compute the reward vector to use in the computation. storm::dd::Add subvector = rewardModel.getTotalRewardVector(maybeStatesAdd, submatrix, model.getColumnVariables()); if (!rewardModel.hasStateActionRewards() && !rewardModel.hasTransitionRewards()) { // If the reward model neither has state-action nor transition rewards, we need to multiply // it with the legal nondetermism encodings in each state. - subvector *= transitionMatrixBdd.existsAbstract(model.getColumnVariables()).template toAdd(); + subvector *= choiceFilterAdd; } - // Since we are cutting away target and infinity states, we need to account for this by giving - // choices the value infinity that have some successor contained in the infinity states. - storm::dd::Bdd choicesWithInfinitySuccessor = (maybeStates && transitionMatrixBdd && infinityStates.swapVariables(model.getRowColumnMetaVariablePairs())).existsAbstract(model.getColumnVariables()); - subvector = choicesWithInfinitySuccessor.ite(model.getManager().template getInfinity(), subvector); - // Before cutting the non-maybe columns, we need to compute the sizes of the row groups. storm::dd::Add stateActionAdd = submatrix.notZero().existsAbstract(model.getColumnVariables()).template toAdd(); std::vector rowGroupSizes = stateActionAdd.sumAbstract(model.getNondeterminismVariables()).toVector(odd); - // Finally cut away all columns targeting non-maybe states. - submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); - - // Create the solution vector. - std::vector x(maybeStates.getNonZeroCount(), storm::utility::zero()); + // Finally cut away all columns targeting non-maybe states (or non-(maybe or target) states, respectively). + submatrix *= requireInitialScheduler ? maybeStatesWithTargetStates.swapVariables(model.getRowColumnMetaVariablePairs()).template toAdd() : maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); // Translate the symbolic matrix/vector to their explicit representations. std::pair, std::vector> explicitRepresentation = submatrix.toMatrixVector(subvector, std::move(rowGroupSizes), model.getNondeterminismVariables(), odd, odd); + // Compute a valid initial scheduler if necessary. + boost::optional> initialScheduler; + boost::optional properMaybeStates; + if (requireInitialScheduler) { + // Compute a valid initial scheduler. + storm::storage::BitVector targetStates = computeTargetStatesForReachabilityRewardsFromExplicitRepresentation(explicitRepresentation.first); + properMaybeStates = ~targetStates; + initialScheduler = computeValidInitialSchedulerForReachabilityRewards(explicitRepresentation.first, properMaybeStates.get(), targetStates); + + // Since we needed the transitions to target states to be translated as well for the computation + // of the scheduler, we have to get rid of them now. + eliminateTargetStatesFromExplicitRepresentation(explicitRepresentation, initialScheduler.get(), properMaybeStates.get()); + } + + // Create the solution vector. + std::vector x(explicitRepresentation.first.getRowGroupCount(), storm::utility::zero()); + // Now solve the resulting equation system. std::unique_ptr> solver = linearEquationSolverFactory.create(std::move(explicitRepresentation.first)); + + // Move the scheduler to the solver. + if (initialScheduler) { + solver->setInitialScheduler(std::move(initialScheduler.get())); + } + + solver->setRequirementsChecked(); solver->solveEquations(dir, x, explicitRepresentation.second); + // If we included the target states in the ODD, we need to expand the result from the solver. + if (requireInitialScheduler) { + x = insertTargetStateValuesIntoExplicitRepresentation(x, properMaybeStates.get()); + } + // Return a hybrid check result that stores the numerical values explicitly. return std::unique_ptr(new storm::modelchecker::HybridQuantitativeCheckResult(model.getReachableStates(), model.getReachableStates() && !maybeStates, infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), model.getManager().template getAddZero()), maybeStates, odd, x)); } else { diff --git a/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp index 6d219bda6..67db97164 100644 --- a/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp @@ -6,20 +6,30 @@ #include "storm/utility/vector.h" #include "storm/utility/graph.h" +#include "storm/storage/StronglyConnectedComponentDecomposition.h" +#include "storm/storage/DynamicPriorityQueue.h" +#include "storm/storage/ConsecutiveUint64DynamicPriorityQueue.h" + #include "storm/solver/LinearEquationSolver.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "storm/modelchecker/hints/ExplicitModelCheckerHint.h" +#include "storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.h" + +#include "storm/utility/macros.h" +#include "storm/utility/ConstantsComparator.h" #include "storm/exceptions/InvalidStateException.h" #include "storm/exceptions/InvalidPropertyException.h" #include "storm/exceptions/IllegalArgumentException.h" +#include "storm/exceptions/UncheckedRequirementException.h" +#include "storm/exceptions/NotSupportedException.h" namespace storm { namespace modelchecker { namespace helper { template - std::vector SparseDtmcPrctlHelper::computeBoundedUntilProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, uint_fast64_t stepBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint) { + std::vector SparseDtmcPrctlHelper::computeBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, uint_fast64_t stepBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint) { std::vector result(transitionMatrix.getRowCount(), storm::utility::zero()); // If we identify the states that have probability 0 of reaching the target states, we can exclude them in the further analysis. @@ -30,9 +40,10 @@ namespace storm { } else { maybeStates = storm::utility::graph::performProbGreater0(backwardTransitions, phiStates, psiStates, true, stepBound); maybeStates &= ~psiStates; - STORM_LOG_INFO("Found " << maybeStates.getNumberOfSetBits() << " 'maybe' states."); } + STORM_LOG_INFO("Preprocessing: " << maybeStates.getNumberOfSetBits() << " non-target states with probability greater 0."); + storm::utility::vector::setVectorValues(result, psiStates, storm::utility::one()); if (!maybeStates.empty()) { @@ -46,7 +57,8 @@ namespace storm { std::vector subresult(maybeStates.getNumberOfSetBits()); // Perform the matrix vector multiplication as often as required by the formula bound. - std::unique_ptr> solver = linearEquationSolverFactory.create(std::move(submatrix)); + goal.restrictRelevantValues(maybeStates); + std::unique_ptr> solver = storm::solver::configureLinearEquationSolver(std::move(goal), linearEquationSolverFactory, std::move(submatrix)); solver->repeatedMultiply(subresult, &b, stepBound); // Set the values of the resulting vector accordingly. @@ -58,7 +70,7 @@ namespace storm { template - std::vector SparseDtmcPrctlHelper::computeUntilProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint) { + std::vector SparseDtmcPrctlHelper::computeUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint) { std::vector result(transitionMatrix.getRowCount(), storm::utility::zero()); @@ -81,18 +93,17 @@ namespace storm { STORM_LOG_THROW(storm::utility::isZero(resultsForNonMaybeStates[state]), storm::exceptions::IllegalArgumentException, "Expected that the result hint specifies probabilities in {0,1} for non-maybe states"); } } + + STORM_LOG_INFO("Preprocessing: " << statesWithProbability1.getNumberOfSetBits() << " states with probability 1 (" << maybeStates.getNumberOfSetBits() << " states remaining)."); } else { - // Get all states that have probability 0 and 1 of satisfying the until-formula. std::pair statesWithProbability01 = storm::utility::graph::performProb01(backwardTransitions, phiStates, psiStates); storm::storage::BitVector statesWithProbability0 = std::move(statesWithProbability01.first); statesWithProbability1 = std::move(statesWithProbability01.second); maybeStates = ~(statesWithProbability0 | statesWithProbability1); - - STORM_LOG_INFO("Found " << statesWithProbability0.getNumberOfSetBits() << " 'no' states."); - STORM_LOG_INFO("Found " << statesWithProbability1.getNumberOfSetBits() << " 'yes' states."); - STORM_LOG_INFO("Found " << maybeStates.getNumberOfSetBits() << " 'maybe' states."); - + + STORM_LOG_INFO("Preprocessing: " << statesWithProbability1.getNumberOfSetBits() << " states with probability 1, " << statesWithProbability0.getNumberOfSetBits() << " with probability 0 (" << maybeStates.getNumberOfSetBits() << " states remaining)."); + // Set values of resulting vector that are known exactly. storm::utility::vector::setVectorValues(result, statesWithProbability0, storm::utility::zero()); storm::utility::vector::setVectorValues(result, statesWithProbability1, storm::utility::one()); @@ -106,12 +117,16 @@ namespace storm { if (!maybeStates.empty()) { // In this case we have have to compute the probabilities. - // We can eliminate the rows and columns from the original transition probability matrix. - storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, true); + // Check whether we need to convert the input to equation system format. + bool convertToEquationSystem = linearEquationSolverFactory.getEquationProblemFormat() == storm::solver::LinearEquationSolverProblemFormat::EquationSystem; - // Converting the matrix from the fixpoint notation to the form needed for the equation - // system. That is, we go from x = A*x + b to (I-A)x = b. - submatrix.convertToEquationSystem(); + // We can eliminate the rows and columns from the original transition probability matrix. + storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, convertToEquationSystem); + if (convertToEquationSystem) { + // Converting the matrix from the fixpoint notation to the form needed for the equation + // system. That is, we go from x = A*x + b to (I-A)x = b. + submatrix.convertToEquationSystem(); + } // Initialize the x vector with the hint (if available) or with 0.5 for each element. // This is the initial guess for the iterative solvers. It should be safe as for all @@ -128,7 +143,8 @@ namespace storm { std::vector b = transitionMatrix.getConstrainedRowSumVector(maybeStates, statesWithProbability1); // Now solve the created system of linear equations. - std::unique_ptr> solver = linearEquationSolverFactory.create(std::move(submatrix)); + goal.restrictRelevantValues(maybeStates); + std::unique_ptr> solver = storm::solver::configureLinearEquationSolver(std::move(goal), linearEquationSolverFactory, std::move(submatrix)); solver->setBounds(storm::utility::zero(), storm::utility::one()); solver->solveEquations(x, b); @@ -140,8 +156,9 @@ namespace storm { } template - std::vector SparseDtmcPrctlHelper::computeGloballyProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { - std::vector result = computeUntilProbabilities(transitionMatrix, backwardTransitions, storm::storage::BitVector(transitionMatrix.getRowCount(), true), ~psiStates, qualitative, linearEquationSolverFactory); + std::vector SparseDtmcPrctlHelper::computeGloballyProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + goal.oneMinus(); + std::vector result = computeUntilProbabilities(std::move(goal), transitionMatrix, backwardTransitions, storm::storage::BitVector(transitionMatrix.getRowCount(), true), ~psiStates, qualitative, linearEquationSolverFactory); for (auto& entry : result) { entry = storm::utility::one() - entry; } @@ -161,7 +178,7 @@ namespace storm { } template - std::vector SparseDtmcPrctlHelper::computeCumulativeRewards(storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseDtmcPrctlHelper::computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { // Initialize result to the null vector. std::vector result(transitionMatrix.getRowCount()); @@ -169,14 +186,14 @@ namespace storm { std::vector totalRewardVector = rewardModel.getTotalRewardVector(transitionMatrix); // Perform the matrix vector multiplication as often as required by the formula bound. - std::unique_ptr> solver = linearEquationSolverFactory.create(transitionMatrix); + std::unique_ptr> solver = storm::solver::configureLinearEquationSolver(std::move(goal), linearEquationSolverFactory, transitionMatrix); solver->repeatedMultiply(result, &totalRewardVector, stepBound); return result; } template - std::vector SparseDtmcPrctlHelper::computeInstantaneousRewards(storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseDtmcPrctlHelper::computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { // Only compute the result if the model has a state-based reward this->getModel(). STORM_LOG_THROW(rewardModel.hasStateRewards(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); @@ -184,21 +201,21 @@ namespace storm { std::vector result = rewardModel.getStateRewardVector(); // Perform the matrix vector multiplication as often as required by the formula bound. - std::unique_ptr> solver = linearEquationSolverFactory.create(transitionMatrix); + std::unique_ptr> solver = storm::solver::configureLinearEquationSolver(std::move(goal), linearEquationSolverFactory, transitionMatrix); solver->repeatedMultiply(result, nullptr, stepCount); return result; } template - std::vector SparseDtmcPrctlHelper::computeReachabilityRewards(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint) { - return computeReachabilityRewards(transitionMatrix, backwardTransitions, [&] (uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates); }, targetStates, qualitative, linearEquationSolverFactory, hint); + std::vector SparseDtmcPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint) { + return computeReachabilityRewards(std::move(goal), transitionMatrix, backwardTransitions, [&] (uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates); }, targetStates, qualitative, linearEquationSolverFactory, hint); } template - std::vector SparseDtmcPrctlHelper::computeReachabilityRewards(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& totalStateRewardVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint) { + std::vector SparseDtmcPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& totalStateRewardVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint) { - return computeReachabilityRewards(transitionMatrix, backwardTransitions, + return computeReachabilityRewards(std::move(goal), transitionMatrix, backwardTransitions, [&] (uint_fast64_t numberOfRows, storm::storage::SparseMatrix const&, storm::storage::BitVector const& maybeStates) { std::vector result(numberOfRows); storm::utility::vector::selectVectorValues(result, maybeStates, totalStateRewardVector); @@ -207,8 +224,21 @@ namespace storm { targetStates, qualitative, linearEquationSolverFactory, hint); } + // This function computes an upper bound on the reachability rewards (see Baier et al, CAV'17). + template + std::vector computeUpperRewardBounds(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& rewards, std::vector const& oneStepTargetProbabilities) { + DsMpiDtmcUpperRewardBoundsComputer dsmpi(transitionMatrix, rewards, oneStepTargetProbabilities); + std::vector bounds = dsmpi.computeUpperBounds(); + return bounds; + } + + template<> + std::vector computeUpperRewardBounds(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& rewards, std::vector const& oneStepTargetProbabilities) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Computing upper reward bounds is not supported for rational functions."); + } + template - std::vector SparseDtmcPrctlHelper::computeReachabilityRewards(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint) { + std::vector SparseDtmcPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint) { std::vector result(transitionMatrix.getRowCount(), storm::utility::zero()); @@ -217,15 +247,15 @@ namespace storm { if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().getComputeOnlyMaybeStates()) { maybeStates = hint.template asExplicitModelCheckerHint().getMaybeStates(); storm::utility::vector::setVectorValues(result, ~(maybeStates | targetStates), storm::utility::infinity()); + + STORM_LOG_INFO("Preprocessing: " << targetStates.getNumberOfSetBits() << " target states (" << maybeStates.getNumberOfSetBits() << " states remaining)."); } else { storm::storage::BitVector trueStates(transitionMatrix.getRowCount(), true); storm::storage::BitVector infinityStates = storm::utility::graph::performProb1(backwardTransitions, trueStates, targetStates); infinityStates.complement(); maybeStates = ~(targetStates | infinityStates); - STORM_LOG_INFO("Found " << infinityStates.getNumberOfSetBits() << " 'infinity' states."); - STORM_LOG_INFO("Found " << targetStates.getNumberOfSetBits() << " 'target' states."); - STORM_LOG_INFO("Found " << maybeStates.getNumberOfSetBits() << " 'maybe' states."); + STORM_LOG_INFO("Preprocessing: " << infinityStates.getNumberOfSetBits() << " states with reward infinity, " << targetStates.getNumberOfSetBits() << " target states (" << maybeStates.getNumberOfSetBits() << " states remaining)."); storm::utility::vector::setVectorValues(result, infinityStates, storm::utility::infinity()); } @@ -237,18 +267,22 @@ namespace storm { storm::utility::vector::setVectorValues(result, maybeStates, storm::utility::one()); } else { if (!maybeStates.empty()) { + // Check whether we need to convert the input to equation system format. + bool convertToEquationSystem = linearEquationSolverFactory.getEquationProblemFormat() == storm::solver::LinearEquationSolverProblemFormat::EquationSystem; + // In this case we have to compute the reward values for the remaining states. // We can eliminate the rows and columns from the original transition probability matrix. - storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, true); - - // Converting the matrix from the fixpoint notation to the form needed for the equation - // system. That is, we go from x = A*x + b to (I-A)x = b. - submatrix.convertToEquationSystem(); + storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, convertToEquationSystem); + if (convertToEquationSystem) { + // Converting the matrix from the fixpoint notation to the form needed for the equation + // system. That is, we go from x = A*x + b to (I-A)x = b. + submatrix.convertToEquationSystem(); + } // Initialize the x vector with the hint (if available) or with 1 for each element. // This is the initial guess for the iterative solvers. std::vector x; - if(hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().hasResultHint()) { + if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().hasResultHint()) { x = storm::utility::vector::filterVector(hint.template asExplicitModelCheckerHint().getResultHint(), maybeStates); } else { x = std::vector(submatrix.getColumnCount(), storm::utility::one()); @@ -256,10 +290,25 @@ namespace storm { // Prepare the right-hand side of the equation system. std::vector b = totalStateRewardVectorGetter(submatrix.getRowCount(), transitionMatrix, maybeStates); + + storm::solver::LinearEquationSolverRequirements requirements = linearEquationSolverFactory.getRequirements(); + boost::optional> upperRewardBounds; + requirements.clearLowerBounds(); + if (requirements.requiresUpperBounds()) { + upperRewardBounds = computeUpperRewardBounds(submatrix, b, transitionMatrix.getConstrainedRowSumVector(maybeStates, targetStates)); + requirements.clearUpperBounds(); + } + STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "There are unchecked requirements of the solver."); - // Now solve the resulting equation system. - std::unique_ptr> solver = linearEquationSolverFactory.create(std::move(submatrix)); + // Create the solver. + goal.restrictRelevantValues(maybeStates); + std::unique_ptr> solver = storm::solver::configureLinearEquationSolver(std::move(goal), linearEquationSolverFactory, std::move(submatrix)); solver->setLowerBound(storm::utility::zero()); + if (upperRewardBounds) { + solver->setUpperBounds(std::move(upperRewardBounds.get())); + } + + // Now solve the resulting equation system. solver->solveEquations(x, b); // Set values of resulting vector according to result. @@ -270,18 +319,18 @@ namespace storm { } template - std::vector SparseDtmcPrctlHelper::computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& psiStates, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { - return SparseCtmcCslHelper::computeLongRunAverageProbabilities(transitionMatrix, psiStates, nullptr, linearEquationSolverFactory); + std::vector SparseDtmcPrctlHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& psiStates, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + return SparseCtmcCslHelper::computeLongRunAverageProbabilities(std::move(goal), transitionMatrix, psiStates, nullptr, linearEquationSolverFactory); } template - std::vector SparseDtmcPrctlHelper::computeLongRunAverageRewards(storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { - return SparseCtmcCslHelper::computeLongRunAverageRewards(transitionMatrix, rewardModel, nullptr, linearEquationSolverFactory); + std::vector SparseDtmcPrctlHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + return SparseCtmcCslHelper::computeLongRunAverageRewards(std::move(goal), transitionMatrix, rewardModel, nullptr, linearEquationSolverFactory); } template - std::vector SparseDtmcPrctlHelper::computeLongRunAverageRewards(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& stateRewards, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { - return SparseCtmcCslHelper::computeLongRunAverageRewards(transitionMatrix, stateRewards, nullptr, linearEquationSolverFactory); + std::vector SparseDtmcPrctlHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, std::vector const& stateRewards, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + return SparseCtmcCslHelper::computeLongRunAverageRewards(std::move(goal), transitionMatrix, stateRewards, nullptr, linearEquationSolverFactory); } template @@ -290,7 +339,7 @@ namespace storm { BaierTransformedModel result; // Start by computing all 'before' states, i.e. the states for which the conditional probability is defined. - std::vector probabilitiesToReachConditionStates = computeUntilProbabilities(transitionMatrix, backwardTransitions, storm::storage::BitVector(transitionMatrix.getRowCount(), true), conditionStates, false, linearEquationSolverFactory); + std::vector probabilitiesToReachConditionStates = computeUntilProbabilities(storm::solver::SolveGoal(), transitionMatrix, backwardTransitions, storm::storage::BitVector(transitionMatrix.getRowCount(), true), conditionStates, false, linearEquationSolverFactory); result.beforeStates = storm::storage::BitVector(targetStates.size(), true); uint_fast64_t state = 0; @@ -405,7 +454,7 @@ namespace storm { } template - std::vector SparseDtmcPrctlHelper::computeConditionalProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseDtmcPrctlHelper::computeConditionalProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { // Prepare result vector. std::vector result(transitionMatrix.getRowCount(), storm::utility::infinity()); @@ -422,7 +471,7 @@ namespace storm { // Now compute reachability probabilities in the transformed model. storm::storage::SparseMatrix const& newTransitionMatrix = transformedModel.transitionMatrix.get(); - std::vector conditionalProbabilities = computeUntilProbabilities(newTransitionMatrix, newTransitionMatrix.transpose(), storm::storage::BitVector(newTransitionMatrix.getRowCount(), true), transformedModel.targetStates.get(), qualitative, linearEquationSolverFactory); + std::vector conditionalProbabilities = computeUntilProbabilities(std::move(goal), newTransitionMatrix, newTransitionMatrix.transpose(), storm::storage::BitVector(newTransitionMatrix.getRowCount(), true), transformedModel.targetStates.get(), qualitative, linearEquationSolverFactory); storm::utility::vector::setVectorValues(result, transformedModel.beforeStates, conditionalProbabilities); } @@ -432,7 +481,7 @@ namespace storm { } template - std::vector SparseDtmcPrctlHelper::computeConditionalRewards(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseDtmcPrctlHelper::computeConditionalRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { // Prepare result vector. std::vector result(transitionMatrix.getRowCount(), storm::utility::infinity()); @@ -448,7 +497,7 @@ namespace storm { // Now compute reachability probabilities in the transformed model. storm::storage::SparseMatrix const& newTransitionMatrix = transformedModel.transitionMatrix.get(); - std::vector conditionalRewards = computeReachabilityRewards(newTransitionMatrix, newTransitionMatrix.transpose(), transformedModel.stateRewards.get(), transformedModel.targetStates.get(), qualitative, linearEquationSolverFactory); + std::vector conditionalRewards = computeReachabilityRewards(std::move(goal), newTransitionMatrix, newTransitionMatrix.transpose(), transformedModel.stateRewards.get(), transformedModel.targetStates.get(), qualitative, linearEquationSolverFactory); storm::utility::vector::setVectorValues(result, transformedModel.beforeStates, conditionalRewards); } } diff --git a/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h b/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h index 12f545d00..46cd0f05a 100644 --- a/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h +++ b/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h @@ -12,6 +12,7 @@ #include "storm/storage/BitVector.h" #include "storm/solver/LinearEquationSolver.h" +#include "storm/solver/SolveGoal.h" namespace storm { namespace modelchecker { @@ -22,35 +23,34 @@ namespace storm { template > class SparseDtmcPrctlHelper { public: - static std::vector computeBoundedUntilProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, uint_fast64_t stepBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); + static std::vector computeBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, uint_fast64_t stepBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); static std::vector computeNextProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& nextStates, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - static std::vector computeUntilProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); + static std::vector computeUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); - static std::vector computeGloballyProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeGloballyProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - static std::vector computeCumulativeRewards(storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - static std::vector computeInstantaneousRewards(storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - - static std::vector computeReachabilityRewards(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); + static std::vector computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); - static std::vector computeReachabilityRewards(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& totalStateRewardVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); + static std::vector computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& totalStateRewardVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); - static std::vector computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& psiStates, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeLongRunAverageProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& psiStates, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - static std::vector computeLongRunAverageRewards(storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - static std::vector computeLongRunAverageRewards(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& stateRewards, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, std::vector const& stateRewards, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - static std::vector computeConditionalProbabilities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeConditionalProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - static std::vector computeConditionalRewards(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeConditionalRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); private: - static std::vector computeReachabilityRewards(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); + static std::vector computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); struct BaierTransformedModel { BaierTransformedModel() : noTargetStates(false) { diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index 6dba4aeab..a000b2e66 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -2,9 +2,10 @@ #include - #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "storm/modelchecker/hints/ExplicitModelCheckerHint.h" +#include "storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.h" +#include "storm/modelchecker/prctl/helper/BaierUpperRewardBoundsComputer.h" #include "storm/models/sparse/StandardRewardModel.h" @@ -29,13 +30,15 @@ #include "storm/exceptions/InvalidSettingsException.h" #include "storm/exceptions/IllegalFunctionCallException.h" #include "storm/exceptions/IllegalArgumentException.h" +#include "storm/exceptions/UncheckedRequirementException.h" +#include "storm/exceptions/NotSupportedException.h" namespace storm { namespace modelchecker { namespace helper { template - std::vector SparseMdpPrctlHelper::computeStepBoundedUntilProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) { + std::vector SparseMdpPrctlHelper::computeStepBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) { std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); // Determine the states that have 0 probability of reaching the target states. @@ -43,15 +46,16 @@ namespace storm { if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().getComputeOnlyMaybeStates()) { maybeStates = hint.template asExplicitModelCheckerHint().getMaybeStates(); } else { - if (dir == OptimizationDirection::Minimize) { + if (goal.minimize()) { maybeStates = storm::utility::graph::performProbGreater0A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates, true, stepBound); } else { maybeStates = storm::utility::graph::performProbGreater0E(backwardTransitions, phiStates, psiStates, true, stepBound); } maybeStates &= ~psiStates; - STORM_LOG_INFO("Found " << maybeStates.getNumberOfSetBits() << " 'maybe' states."); } + STORM_LOG_INFO("Preprocessing: " << maybeStates.getNumberOfSetBits() << " non-target states with probability greater 0."); + if (!maybeStates.empty()) { // We can eliminate the rows and columns from the original transition probability matrix that have probability 0. storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false); @@ -60,8 +64,9 @@ namespace storm { // Create the vector with which to multiply. std::vector subresult(maybeStates.getNumberOfSetBits()); - std::unique_ptr> solver = minMaxLinearEquationSolverFactory.create(std::move(submatrix)); - solver->repeatedMultiply(dir, subresult, &b, stepBound); + goal.restrictRelevantValues(maybeStates); + std::unique_ptr> solver = storm::solver::configureMinMaxLinearEquationSolver(std::move(goal), minMaxLinearEquationSolverFactory, std::move(submatrix)); + solver->repeatedMultiply(subresult, &b, stepBound); // Set the values of the resulting vector accordingly. storm::utility::vector::setVectorValues(result, maybeStates, subresult); @@ -133,209 +138,671 @@ namespace storm { } template - MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeUntilProbabilities(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) { - STORM_LOG_THROW(!(qualitative && produceScheduler), storm::exceptions::InvalidSettingsException, "Cannot produce scheduler when performing qualitative model checking only."); - - std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); - - // We need to identify the maybe states (states which have a probability for satisfying the until formula - // that is strictly between 0 and 1) and the states that satisfy the formula with probablity 1 and 0, respectively. - storm::storage::BitVector maybeStates, statesWithProbability1, statesWithProbability0; + std::vector computeValidSchedulerHint(storm::solver::EquationSystemType const& type, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& maybeStates, storm::storage::BitVector const& filterStates, storm::storage::BitVector const& targetStates) { + storm::storage::Scheduler validScheduler(maybeStates.size()); + + if (type == storm::solver::EquationSystemType::UntilProbabilities) { + storm::utility::graph::computeSchedulerProbGreater0E(transitionMatrix, backwardTransitions, filterStates, targetStates, validScheduler, boost::none); + } else if (type == storm::solver::EquationSystemType::ReachabilityRewards) { + storm::utility::graph::computeSchedulerProb1E(maybeStates | targetStates, transitionMatrix, backwardTransitions, filterStates, targetStates, validScheduler); + } else { + STORM_LOG_ASSERT(false, "Unexpected equation system type."); + } - if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().getComputeOnlyMaybeStates()) { - maybeStates = hint.template asExplicitModelCheckerHint().getMaybeStates(); - - // Treat the states with probability one - std::vector const& resultsForNonMaybeStates = hint.template asExplicitModelCheckerHint().getResultHint(); - statesWithProbability1 = storm::storage::BitVector(maybeStates.size(), false); - statesWithProbability0 = storm::storage::BitVector(maybeStates.size(), false); - storm::storage::BitVector nonMaybeStates = ~maybeStates; - for (auto const& state : nonMaybeStates) { - if (storm::utility::isOne(resultsForNonMaybeStates[state])) { - statesWithProbability1.set(state, true); - result[state] = storm::utility::one(); + // Extract the relevant parts of the scheduler for the solver. + std::vector schedulerHint(maybeStates.getNumberOfSetBits()); + auto maybeIt = maybeStates.begin(); + for (auto& choice : schedulerHint) { + choice = validScheduler.getChoice(*maybeIt).getDeterministicChoice(); + ++maybeIt; + } + return schedulerHint; + } + + template + struct SparseMdpHintType { + SparseMdpHintType() : eliminateEndComponents(false), computeUpperBounds(false) { + // Intentionally left empty. + } + + bool hasSchedulerHint() const { + return static_cast(schedulerHint); + } + + bool hasValueHint() const { + return static_cast(valueHint); + } + + bool hasLowerResultBound() const { + return static_cast(lowerResultBound); + } + + ValueType const& getLowerResultBound() const { + return lowerResultBound.get(); + } + + bool hasUpperResultBound() const { + return static_cast(upperResultBound); + } + + bool hasUpperResultBounds() const { + return static_cast(upperResultBounds); + } + + ValueType const& getUpperResultBound() const { + return upperResultBound.get(); + } + + std::vector& getUpperResultBounds() { + return upperResultBounds.get(); + } + + std::vector const& getUpperResultBounds() const { + return upperResultBounds.get(); + } + + std::vector& getSchedulerHint() { + return schedulerHint.get(); + } + + std::vector& getValueHint() { + return valueHint.get(); + } + + bool getEliminateEndComponents() const { + return eliminateEndComponents; + } + + bool getComputeUpperBounds() { + return computeUpperBounds; + } + + boost::optional> schedulerHint; + boost::optional> valueHint; + boost::optional lowerResultBound; + boost::optional upperResultBound; + boost::optional> upperResultBounds; + bool eliminateEndComponents; + bool computeUpperBounds; + }; + + template + void extractValueAndSchedulerHint(SparseMdpHintType& hintStorage, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& maybeStates, boost::optional const& selectedChoices, ModelCheckerHint const& hint, bool skipECWithinMaybeStatesCheck) { + + // Deal with scheduler hint. + if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().hasSchedulerHint()) { + if (hintStorage.hasSchedulerHint()) { + STORM_LOG_WARN("A scheduler hint was provided, but the solver requires a specific one. The provided scheduler hint will be ignored."); + } else { + auto const& schedulerHint = hint.template asExplicitModelCheckerHint().getSchedulerHint(); + std::vector hintChoices; + + // The scheduler hint is only applicable if it induces no BSCC consisting of maybe states. + bool hintApplicable; + if (!skipECWithinMaybeStatesCheck) { + hintChoices.reserve(maybeStates.size()); + for (uint_fast64_t state = 0; state < maybeStates.size(); ++state) { + hintChoices.push_back(schedulerHint.getChoice(state).getDeterministicChoice()); + } + hintApplicable = storm::utility::graph::performProb1(transitionMatrix.transposeSelectedRowsFromRowGroups(hintChoices), maybeStates, ~maybeStates).full(); } else { - STORM_LOG_THROW(storm::utility::isZero(resultsForNonMaybeStates[state]), storm::exceptions::IllegalArgumentException, "Expected that the result hint specifies probabilities in {0,1} for non-maybe states"); - statesWithProbability0.set(state, true); + hintApplicable = true; + } + + if (hintApplicable) { + // Compute the hint w.r.t. the given subsystem. + hintChoices.clear(); + hintChoices.reserve(maybeStates.getNumberOfSetBits()); + for (auto const& state : maybeStates) { + uint_fast64_t hintChoice = schedulerHint.getChoice(state).getDeterministicChoice(); + if (selectedChoices) { + uint_fast64_t firstChoice = transitionMatrix.getRowGroupIndices()[state]; + uint_fast64_t lastChoice = firstChoice + hintChoice; + hintChoice = 0; + for (uint_fast64_t choice = selectedChoices->getNextSetIndex(firstChoice); choice < lastChoice; choice = selectedChoices->getNextSetIndex(choice + 1)) { + ++hintChoice; + } + } + hintChoices.push_back(hintChoice); + } + hintStorage.schedulerHint = std::move(hintChoices); } } - } else { - // Get all states that have probability 0 and 1 of satisfying the until-formula. - std::pair statesWithProbability01; - if (goal.minimize()) { - statesWithProbability01 = storm::utility::graph::performProb01Min(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates); - } else { - statesWithProbability01 = storm::utility::graph::performProb01Max(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates); + } + + // Deal with solution value hint. Only applicable if there are no End Components consisting of maybe states. + if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().hasResultHint() && (skipECWithinMaybeStatesCheck || hintStorage.hasSchedulerHint() || storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, maybeStates, ~maybeStates).full())) { + hintStorage.valueHint = storm::utility::vector::filterVector(hint.template asExplicitModelCheckerHint().getResultHint(), maybeStates); + } + } + + template + SparseMdpHintType computeHints(storm::solver::EquationSystemType const& type, ModelCheckerHint const& hint, storm::OptimizationDirection const& dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& maybeStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& targetStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, boost::optional const& selectedChoices = boost::none) { + SparseMdpHintType result; + + // Check for requirements of the solver. + storm::solver::MinMaxLinearEquationSolverRequirements requirements = minMaxLinearEquationSolverFactory.getRequirements(type, dir); + if (!requirements.empty()) { + // If the hint tells us that there are no end-components, we can clear that requirement. + if (hint.isExplicitModelCheckerHint() && hint.asExplicitModelCheckerHint().getNoEndComponentsInMaybeStates()) { + requirements.clearNoEndComponents(); + } + + // If the solver still requires no end-components, we have to eliminate them later. + if (requirements.requiresNoEndComponents()) { + STORM_LOG_DEBUG("Scheduling EC elimination, because the solver requires it."); + result.eliminateEndComponents = true; + requirements.clearNoEndComponents(); } - statesWithProbability0 = std::move(statesWithProbability01.first); - statesWithProbability1 = std::move(statesWithProbability01.second); - maybeStates = ~(statesWithProbability0 | statesWithProbability1); - STORM_LOG_INFO("Found " << statesWithProbability0.getNumberOfSetBits() << " 'no' states."); - STORM_LOG_INFO("Found " << statesWithProbability1.getNumberOfSetBits() << " 'yes' states."); - STORM_LOG_INFO("Found " << maybeStates.getNumberOfSetBits() << " 'maybe' states."); + + // If the solver requires an initial scheduler, compute one now. + if (requirements.requires(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler)) { + STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it."); + result.schedulerHint = computeValidSchedulerHint(type, transitionMatrix, backwardTransitions, maybeStates, phiStates, targetStates); + requirements.clearValidInitialScheduler(); + } + + // Finally, we have information on the bounds depending on the problem type. + if (type == storm::solver::EquationSystemType::UntilProbabilities) { + requirements.clearBounds(); + } else if (type == storm::solver::EquationSystemType::ReachabilityRewards) { + requirements.clearLowerBounds(); + } + if (requirements.requiresUpperBounds()) { + result.computeUpperBounds = true; + requirements.clearUpperBounds(); + } + STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "There are unchecked requirements of the solver."); + } else { + STORM_LOG_DEBUG("Solver has no requirements."); + } + + // Only if there is no end component decomposition that we will need to do later, we use value and scheduler + // hints from the provided hint. + if (!result.eliminateEndComponents) { + bool skipEcWithinMaybeStatesCheck = dir == storm::OptimizationDirection::Minimize || (hint.isExplicitModelCheckerHint() && hint.asExplicitModelCheckerHint().getNoEndComponentsInMaybeStates()); + extractValueAndSchedulerHint(result, transitionMatrix, backwardTransitions, maybeStates, selectedChoices, hint, skipEcWithinMaybeStatesCheck); + } else { + STORM_LOG_WARN_COND(hint.isEmpty(), "A non-empty hint was provided, but its information will be disregarded."); + } + + // Only set bounds if we did not obtain them from the hint. + if (!result.hasLowerResultBound()) { + result.lowerResultBound = storm::utility::zero(); + } + if (!result.hasUpperResultBound() && type == storm::solver::EquationSystemType::UntilProbabilities) { + result.upperResultBound = storm::utility::one(); + } - // Set values of resulting vector that are known exactly. - storm::utility::vector::setVectorValues(result, statesWithProbability0, storm::utility::zero()); - storm::utility::vector::setVectorValues(result, statesWithProbability1, storm::utility::one()); + // If we received an upper bound, we can drop the requirement to compute one. + if (result.hasUpperResultBound()) { + result.computeUpperBounds = false; + } + + return result; + } + + template + struct MaybeStateResult { + MaybeStateResult(std::vector&& values) : values(std::move(values)) { + // Intentionally left empty. } - // If requested, we will produce a scheduler. - std::unique_ptr> scheduler; - if (produceScheduler) { - scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); + bool hasScheduler() const { + return static_cast(scheduler); } - // Check whether we need to compute exact probabilities for some states. - if (qualitative) { - // Set the values for all maybe-states to 0.5 to indicate that their probability values are neither 0 nor 1. - storm::utility::vector::setVectorValues(result, maybeStates, storm::utility::convertNumber(0.5)); - } else { - if (!maybeStates.empty()) { - // In this case we have have to compute the probabilities. - - // First, we can eliminate the rows and columns from the original transition probability matrix for states - // whose probabilities are already known. - storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false); - - // Prepare the right-hand side of the equation system. For entry i this corresponds to - // the accumulated probability of going from state i to some 'yes' state. - std::vector b = transitionMatrix.getConstrainedRowGroupSumVector(maybeStates, statesWithProbability1); - - // obtain hint information if possible - bool skipEcWithinMaybeStatesCheck = goal.minimize() || (hint.isExplicitModelCheckerHint() && hint.asExplicitModelCheckerHint().getNoEndComponentsInMaybeStates()); - std::pair>, boost::optional>> hintInformation = extractHintInformationForMaybeStates(transitionMatrix, backwardTransitions, maybeStates, boost::none, hint, skipEcWithinMaybeStatesCheck); - - // Now compute the results for the maybeStates - std::pair, boost::optional>> resultForMaybeStates = computeValuesOnlyMaybeStates(goal, submatrix, b, produceScheduler, minMaxLinearEquationSolverFactory, std::move(hintInformation.first), std::move(hintInformation.second), storm::utility::zero(), storm::utility::one()); - - // Set values of resulting vector according to result. - storm::utility::vector::setVectorValues(result, maybeStates, resultForMaybeStates.first); - - if (produceScheduler) { - std::vector const& subChoices = resultForMaybeStates.second.get(); - auto subChoiceIt = subChoices.begin(); - for (auto maybeState : maybeStates) { - scheduler->setChoice(*subChoiceIt, maybeState); - ++subChoiceIt; - } - assert(subChoiceIt == subChoices.end()); - } + std::vector const& getScheduler() const { + return scheduler.get(); + } + + std::vector const& getValues() const { + return values; + } + + std::vector values; + boost::optional> scheduler; + }; + + template + MaybeStateResult computeValuesForMaybeStates(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix&& submatrix, std::vector const& b, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, SparseMdpHintType& hint) { + + // Initialize the solution vector. + std::vector x = hint.hasValueHint() ? std::move(hint.getValueHint()) : std::vector(submatrix.getRowGroupCount(), hint.hasLowerResultBound() ? hint.getLowerResultBound() : storm::utility::zero()); + + // Set up the solver. + std::unique_ptr> solver = storm::solver::configureMinMaxLinearEquationSolver(std::move(goal), minMaxLinearEquationSolverFactory, std::move(submatrix)); + solver->setRequirementsChecked(); + if (hint.hasLowerResultBound()) { + solver->setLowerBound(hint.getLowerResultBound()); + } + if (hint.hasUpperResultBound()) { + solver->setUpperBound(hint.getUpperResultBound()); + } + if (hint.hasUpperResultBounds()) { + solver->setUpperBounds(std::move(hint.getUpperResultBounds())); + } + if (hint.hasSchedulerHint()) { + solver->setInitialScheduler(std::move(hint.getSchedulerHint())); + } + solver->setTrackScheduler(produceScheduler); + + // Solve the corresponding system of equations. + solver->solveEquations(x, b); + +#ifndef NDEBUG + // As a sanity check, make sure our local upper bounds were in fact correct. + if (solver->hasUpperBound(storm::solver::AbstractEquationSolver::BoundType::Local)) { + auto resultIt = x.begin(); + for (auto const& entry : solver->getUpperBounds()) { + STORM_LOG_ASSERT(*resultIt <= entry, "Expecting result value for state " << std::distance(x.begin(), resultIt) << " to be <= " << entry << ", but got " << *resultIt << "."); + ++resultIt; } } +#endif - // Finally, if we need to produce a scheduler, we also need to figure out the parts of the scheduler for - // the states with probability 1 or 0 (depending on whether we maximize or minimize). - // We also need to define some arbitrary choice for the remaining states to obtain a fully defined scheduler. + // Create result. + MaybeStateResult result(std::move(x)); + + // If requested, return the requested scheduler. if (produceScheduler) { - if (goal.minimize()) { - storm::utility::graph::computeSchedulerProb0E(statesWithProbability0, transitionMatrix, *scheduler); - for (auto const& prob1State : statesWithProbability1) { - scheduler->setChoice(0, prob1State); - } + result.scheduler = std::move(solver->getSchedulerChoices()); + } + return result; + } + + struct QualitativeStateSetsUntilProbabilities { + storm::storage::BitVector maybeStates; + storm::storage::BitVector statesWithProbability0; + storm::storage::BitVector statesWithProbability1; + }; + + template + QualitativeStateSetsUntilProbabilities getQualitativeStateSetsUntilProbabilitiesFromHint(ModelCheckerHint const& hint) { + QualitativeStateSetsUntilProbabilities result; + result.maybeStates = hint.template asExplicitModelCheckerHint().getMaybeStates(); + + // Treat the states with probability zero/one. + std::vector const& resultsForNonMaybeStates = hint.template asExplicitModelCheckerHint().getResultHint(); + result.statesWithProbability1 = storm::storage::BitVector(result.maybeStates.size()); + result.statesWithProbability0 = storm::storage::BitVector(result.maybeStates.size()); + storm::storage::BitVector nonMaybeStates = ~result.maybeStates; + for (auto const& state : nonMaybeStates) { + if (storm::utility::isOne(resultsForNonMaybeStates[state])) { + result.statesWithProbability1.set(state, true); } else { - storm::utility::graph::computeSchedulerProb1E(statesWithProbability1, transitionMatrix, backwardTransitions, phiStates, psiStates, *scheduler); - for (auto const& prob0State : statesWithProbability0) { - scheduler->setChoice(0, prob0State); - } + STORM_LOG_THROW(storm::utility::isZero(resultsForNonMaybeStates[state]), storm::exceptions::IllegalArgumentException, "Expected that the result hint specifies probabilities in {0,1} for non-maybe states"); + result.statesWithProbability0.set(state, true); } } - STORM_LOG_ASSERT((!produceScheduler && !scheduler) || (!scheduler->isPartialScheduler() && scheduler->isDeterministicScheduler() && scheduler->isMemorylessScheduler()), "Unexpected format of obtained scheduler."); + return result; + } + + template + QualitativeStateSetsUntilProbabilities computeQualitativeStateSetsUntilProbabilities(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) { + QualitativeStateSetsUntilProbabilities result; + // Get all states that have probability 0 and 1 of satisfying the until-formula. + std::pair statesWithProbability01; + if (goal.minimize()) { + statesWithProbability01 = storm::utility::graph::performProb01Min(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates); + } else { + statesWithProbability01 = storm::utility::graph::performProb01Max(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates); + } + result.statesWithProbability0 = std::move(statesWithProbability01.first); + result.statesWithProbability1 = std::move(statesWithProbability01.second); + result.maybeStates = ~(result.statesWithProbability0 | result.statesWithProbability1); - return MDPSparseModelCheckingHelperReturnType(std::move(result), std::move(scheduler)); + return result; + } + + template + QualitativeStateSetsUntilProbabilities getQualitativeStateSetsUntilProbabilities(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, ModelCheckerHint const& hint) { + if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().getComputeOnlyMaybeStates()) { + return getQualitativeStateSetsUntilProbabilitiesFromHint(hint); + } else { + return computeQualitativeStateSetsUntilProbabilities(goal, transitionMatrix, backwardTransitions, phiStates, psiStates); + } } template - std::pair>, boost::optional>> SparseMdpPrctlHelper::extractHintInformationForMaybeStates(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& maybeStates, boost::optional const& selectedChoices, ModelCheckerHint const& hint, bool skipECWithinMaybeStatesCheck) { + void extractSchedulerChoices(storm::storage::Scheduler& scheduler, std::vector const& subChoices, storm::storage::BitVector const& maybeStates) { + auto subChoiceIt = subChoices.begin(); + for (auto maybeState : maybeStates) { + scheduler.setChoice(*subChoiceIt, maybeState); + ++subChoiceIt; + } + assert(subChoiceIt == subChoices.end()); + } + + template + void extendScheduler(storm::storage::Scheduler& scheduler, storm::solver::SolveGoal const& goal, QualitativeStateSetsUntilProbabilities const& qualitativeStateSets, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) { - // Scheduler hint - boost::optional> subSchedulerChoices; - if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().hasSchedulerHint()) { - auto const& schedulerHint = hint.template asExplicitModelCheckerHint().getSchedulerHint(); - std::vector hintChoices; + // Finally, if we need to produce a scheduler, we also need to figure out the parts of the scheduler for + // the states with probability 1 or 0 (depending on whether we maximize or minimize). + // We also need to define some arbitrary choice for the remaining states to obtain a fully defined scheduler. + if (goal.minimize()) { + storm::utility::graph::computeSchedulerProb0E(qualitativeStateSets.statesWithProbability0, transitionMatrix, scheduler); + for (auto const& prob1State : qualitativeStateSets.statesWithProbability1) { + scheduler.setChoice(0, prob1State); + } + } else { + storm::utility::graph::computeSchedulerProb1E(qualitativeStateSets.statesWithProbability1, transitionMatrix, backwardTransitions, phiStates, psiStates, scheduler); + for (auto const& prob0State : qualitativeStateSets.statesWithProbability0) { + scheduler.setChoice(0, prob0State); + } + } + } + + template + void computeFixedPointSystemUntilProbabilities(storm::storage::SparseMatrix const& transitionMatrix, QualitativeStateSetsUntilProbabilities const& qualitativeStateSets, storm::storage::SparseMatrix& submatrix, std::vector& b) { + // First, we can eliminate the rows and columns from the original transition probability matrix for states + // whose probabilities are already known. + submatrix = transitionMatrix.getSubmatrix(true, qualitativeStateSets.maybeStates, qualitativeStateSets.maybeStates, false); + + // Prepare the right-hand side of the equation system. For entry i this corresponds to + // the accumulated probability of going from state i to some state that has probability 1. + b = transitionMatrix.getConstrainedRowGroupSumVector(qualitativeStateSets.maybeStates, qualitativeStateSets.statesWithProbability1); + } + + static const uint64_t NOT_IN_EC = std::numeric_limits::max(); + + template + struct SparseMdpEndComponentInformation { + SparseMdpEndComponentInformation(storm::storage::MaximalEndComponentDecomposition const& endComponentDecomposition, storm::storage::BitVector const& maybeStates) : eliminatedEndComponents(false), numberOfMaybeStatesInEc(0), numberOfMaybeStatesNotInEc(0), numberOfEc(endComponentDecomposition.size()) { + + // (1) Compute how many maybe states there are before each other maybe state. + maybeStatesBefore = maybeStates.getNumberOfSetBitsBeforeIndices(); - // the scheduler hint is only applicable if it induces no BSCC consisting of maybestates - bool hintApplicable; - if (!skipECWithinMaybeStatesCheck) { - hintChoices.reserve(maybeStates.size()); - for (uint_fast64_t state = 0; state < maybeStates.size(); ++state) { - hintChoices.push_back(schedulerHint.getChoice(state).getDeterministicChoice()); - } - hintApplicable = storm::utility::graph::performProb1(transitionMatrix.transposeSelectedRowsFromRowGroups(hintChoices), maybeStates, ~maybeStates).full(); - } else { - hintApplicable = true; + // (2) Create mapping from maybe states to their MEC. If they are not contained in an MEC, their value + // is set to a special constant. + maybeStateToEc.resize(maybeStates.getNumberOfSetBits(), NOT_IN_EC); + uint64_t mecIndex = 0; + for (auto const& mec : endComponentDecomposition) { + for (auto const& stateActions : mec) { + maybeStateToEc[maybeStatesBefore[stateActions.first]] = mecIndex; + ++numberOfMaybeStatesInEc; + } + ++mecIndex; + } + + // (3) Compute number of states not in MECs. + numberOfMaybeStatesNotInEc = maybeStateToEc.size() - numberOfMaybeStatesInEc; + } + + bool isMaybeStateInEc(uint64_t maybeState) const { + return maybeStateToEc[maybeState] != NOT_IN_EC; + } + + bool isStateInEc(uint64_t state) const { + return maybeStateToEc[maybeStatesBefore[state]] != NOT_IN_EC; + } + + std::vector getNumberOfMaybeStatesNotInEcBeforeIndices() const { + std::vector result(maybeStateToEc.size()); + + uint64_t count = 0; + auto resultIt = result.begin(); + for (auto const& e : maybeStateToEc) { + *resultIt = count; + if (e != NOT_IN_EC) { + ++count; + } + ++resultIt; } - if (hintApplicable) { - // Compute the hint w.r.t. the given subsystem - hintChoices.clear(); - hintChoices.reserve(maybeStates.getNumberOfSetBits()); - for (auto const& state : maybeStates) { - uint_fast64_t hintChoice = schedulerHint.getChoice(state).getDeterministicChoice(); - if (selectedChoices) { - uint_fast64_t firstChoice = transitionMatrix.getRowGroupIndices()[state]; - uint_fast64_t lastChoice = firstChoice + hintChoice; - hintChoice = 0; - for (uint_fast64_t choice = selectedChoices->getNextSetIndex(firstChoice); choice < lastChoice; choice = selectedChoices->getNextSetIndex(choice + 1)) { - ++hintChoice; + return result; + } + + uint64_t getEc(uint64_t state) const { + return maybeStateToEc[maybeStatesBefore[state]]; + } + + uint64_t getSubmatrixRowGroupOfStateInEc(uint64_t state) const { + return numberOfMaybeStatesNotInEc + getEc(state); + } + + bool eliminatedEndComponents; + + std::vector maybeStatesBefore; + uint64_t numberOfMaybeStatesInEc; + uint64_t numberOfMaybeStatesNotInEc; + uint64_t numberOfEc; + + std::vector maybeStateToEc; + }; + + template + SparseMdpEndComponentInformation eliminateEndComponents(storm::storage::MaximalEndComponentDecomposition const& endComponentDecomposition, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates, storm::storage::BitVector const* sumColumns, storm::storage::BitVector const* selectedChoices, std::vector const* summand, storm::storage::SparseMatrix& submatrix, std::vector* columnSumVector, std::vector* summandResultVector) { + + SparseMdpEndComponentInformation result(endComponentDecomposition, maybeStates); + + // (1) Compute the number of maybe states not in ECs before any other maybe state. + std::vector maybeStatesNotInEcBefore = result.getNumberOfMaybeStatesNotInEcBeforeIndices(); + uint64_t numberOfStates = result.numberOfMaybeStatesNotInEc + result.numberOfEc; + + STORM_LOG_TRACE("Found " << numberOfStates << " states, " << result.numberOfMaybeStatesNotInEc << " not in ECs, " << result.numberOfMaybeStatesInEc << " in ECs and " << result.numberOfEc << " ECs."); + + // Prepare builder and vector storage. + storm::storage::SparseMatrixBuilder builder(0, numberOfStates, 0, true, true, numberOfStates); + STORM_LOG_ASSERT((sumColumns && columnSumVector) || (!sumColumns && !columnSumVector), "Expecting a bit vector for which columns to sum iff there is a column sum result vector."); + if (columnSumVector) { + columnSumVector->resize(numberOfStates); + } + STORM_LOG_ASSERT((summand && summandResultVector) || (!summand && !summandResultVector), "Expecting summand iff there is a summand result vector."); + if (summandResultVector) { + summandResultVector->resize(numberOfStates); + } + std::vector> ecValuePairs; + + // (2) Create the parts of the submatrix and vector b that belong to states not contained in ECs. + uint64_t currentRow = 0; + for (auto state : maybeStates) { + if (!result.isStateInEc(state)) { + builder.newRowGroup(currentRow); + for (uint64_t row = transitionMatrix.getRowGroupIndices()[state], endRow = transitionMatrix.getRowGroupIndices()[state + 1]; row < endRow; ++row) { + // If the choices is not in the selected ones, drop it. + if (selectedChoices && !selectedChoices->get(row)) { + continue; + } + + ecValuePairs.clear(); + + if (summand) { + (*summandResultVector)[currentRow] += (*summand)[row]; + } + for (auto const& e : transitionMatrix.getRow(row)) { + if (sumColumns && sumColumns->get(e.getColumn())) { + (*columnSumVector)[currentRow] += e.getValue(); + } else if (maybeStates.get(e.getColumn())) { + // If the target state of the transition is not contained in an EC, we can just add the entry. + if (result.isStateInEc(e.getColumn())) { + builder.addNextValue(currentRow, maybeStatesNotInEcBefore[result.maybeStatesBefore[e.getColumn()]], e.getValue()); + } else { + // Otherwise, we store the information that the state can go to a certain EC. + ecValuePairs.emplace_back(result.getEc(e.getColumn()), e.getValue()); + } } } - hintChoices.push_back(hintChoice); + + if (!ecValuePairs.empty()) { + std::sort(ecValuePairs.begin(), ecValuePairs.end()); + + for (auto const& e : ecValuePairs) { + builder.addNextValue(currentRow, result.numberOfMaybeStatesNotInEc + e.first, e.second); + } + } + + ++currentRow; } - subSchedulerChoices = std::move(hintChoices); } } - // Solution value hint - boost::optional> subValues; - // The result hint is only applicable if there are no End Components consisting of maybestates - if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().hasResultHint() && - (skipECWithinMaybeStatesCheck || subSchedulerChoices || - storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, maybeStates, ~maybeStates).full())) { - subValues = storm::utility::vector::filterVector(hint.template asExplicitModelCheckerHint().getResultHint(), maybeStates); + // (3) Create the parts of the submatrix and vector b that belong to states contained in ECs. + for (auto const& mec : endComponentDecomposition) { + builder.newRowGroup(currentRow); + + for (auto const& stateActions : mec) { + uint64_t const& state = stateActions.first; + for (uint64_t row = transitionMatrix.getRowGroupIndices()[state], endRow = transitionMatrix.getRowGroupIndices()[state + 1]; row < endRow; ++row) { + // If the choice is contained in the MEC, drop it. + if (stateActions.second.find(row) != stateActions.second.end()) { + continue; + } + // If the choices is not in the selected ones, drop it. + if (selectedChoices && !selectedChoices->get(row)) { + continue; + } + + ecValuePairs.clear(); + + if (summand) { + (*summandResultVector)[currentRow] += (*summand)[row]; + } + for (auto const& e : transitionMatrix.getRow(row)) { + if (sumColumns && sumColumns->get(e.getColumn())) { + (*columnSumVector)[currentRow] += e.getValue(); + } else if (maybeStates.get(e.getColumn())) { + // If the target state of the transition is not contained in an EC, we can just add the entry. + if (result.isStateInEc(e.getColumn())) { + builder.addNextValue(currentRow, maybeStatesNotInEcBefore[result.maybeStatesBefore[e.getColumn()]], e.getValue()); + } else { + // Otherwise, we store the information that the state can go to a certain EC. + ecValuePairs.emplace_back(result.getEc(e.getColumn()), e.getValue()); + } + } + } + + if (!ecValuePairs.empty()) { + std::sort(ecValuePairs.begin(), ecValuePairs.end()); + + for (auto const& e : ecValuePairs) { + builder.addNextValue(currentRow, result.numberOfMaybeStatesNotInEc + e.first, e.second); + } + } + + ++currentRow; + } + } } - return std::make_pair(std::move(subValues), std::move(subSchedulerChoices)); + + submatrix = builder.build(); + return result; } template - std::pair, boost::optional>> SparseMdpPrctlHelper::computeValuesOnlyMaybeStates(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& submatrix, std::vector const& b, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, boost::optional>&& hintValues, boost::optional>&& hintChoices, boost::optional const& lowerResultBound, boost::optional const& upperResultBound) { + boost::optional> computeFixedPointSystemUntilProbabilitiesEliminateEndComponents(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, QualitativeStateSetsUntilProbabilities const& qualitativeStateSets, storm::storage::SparseMatrix& submatrix, std::vector& b) { - // Set up the solver - std::unique_ptr> solver = storm::solver::configureMinMaxLinearEquationSolver(goal, minMaxLinearEquationSolverFactory, submatrix); - if (lowerResultBound) { - solver->setLowerBound(lowerResultBound.get()); - } - if (upperResultBound) { - solver->setUpperBound(upperResultBound.get()); + // Start by computing the states that are in MECs. + storm::storage::MaximalEndComponentDecomposition endComponentDecomposition(transitionMatrix, backwardTransitions, qualitativeStateSets.maybeStates); + + // Only do more work if there are actually end-components. + if (!endComponentDecomposition.empty()) { + STORM_LOG_DEBUG("Eliminating " << endComponentDecomposition.size() << " ECs."); + return eliminateEndComponents(endComponentDecomposition, transitionMatrix, qualitativeStateSets.maybeStates, &qualitativeStateSets.statesWithProbability1, nullptr, nullptr, submatrix, &b, nullptr); + } else { + STORM_LOG_DEBUG("Not eliminating ECs as there are none."); + computeFixedPointSystemUntilProbabilities(transitionMatrix, qualitativeStateSets, submatrix, b); + return boost::none; } - if (hintChoices) { - solver->setSchedulerHint(std::move(hintChoices.get())); + } + + template + void setResultValuesWrtEndComponents(SparseMdpEndComponentInformation const& ecInformation, std::vector& result, storm::storage::BitVector const& maybeStates, std::vector const& fromResult) { + auto notInEcResultIt = result.begin(); + for (auto state : maybeStates) { + if (ecInformation.isStateInEc(state)) { + result[state] = result[ecInformation.getSubmatrixRowGroupOfStateInEc(state)]; + } else { + result[state] = *notInEcResultIt; + ++notInEcResultIt; + } } - solver->setTrackScheduler(produceScheduler); + STORM_LOG_ASSERT(notInEcResultIt == result.begin() + ecInformation.numberOfMaybeStatesNotInEc, "Mismatching iterators."); + } + + template + MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) { + STORM_LOG_THROW(!qualitative || !produceScheduler, storm::exceptions::InvalidSettingsException, "Cannot produce scheduler when performing qualitative model checking only."); - // Initialize the solution vector. - std::vector x = hintValues ? std::move(hintValues.get()) : std::vector(submatrix.getRowGroupCount(), lowerResultBound ? lowerResultBound.get() : storm::utility::zero()); + // Prepare resulting vector. + std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); + + // We need to identify the maybe states (states which have a probability for satisfying the until formula + // that is strictly between 0 and 1) and the states that satisfy the formula with probablity 1 and 0, respectively. + QualitativeStateSetsUntilProbabilities qualitativeStateSets = getQualitativeStateSetsUntilProbabilities(goal, transitionMatrix, backwardTransitions, phiStates, psiStates, hint); - // Solve the corresponding system of equations. - solver->solveEquations(x, b); + STORM_LOG_INFO("Preprocessing: " << qualitativeStateSets.statesWithProbability1.getNumberOfSetBits() << " states with probability 1, " << qualitativeStateSets.statesWithProbability0.getNumberOfSetBits() << " with probability 0 (" << qualitativeStateSets.maybeStates.getNumberOfSetBits() << " states remaining)."); + + // Set values of resulting vector that are known exactly. + storm::utility::vector::setVectorValues(result, qualitativeStateSets.statesWithProbability1, storm::utility::one()); - // If requested, a scheduler was produced + // If requested, we will produce a scheduler. + std::unique_ptr> scheduler; if (produceScheduler) { - return std::pair, boost::optional>>(std::move(x), std::move(solver->getSchedulerChoices())); + scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); + } + + // Check whether we need to compute exact probabilities for some states. + if (qualitative) { + // Set the values for all maybe-states to 0.5 to indicate that their probability values are neither 0 nor 1. + storm::utility::vector::setVectorValues(result, qualitativeStateSets.maybeStates, storm::utility::convertNumber(0.5)); } else { - return std::pair, boost::optional>>(std::move(x), boost::none); + if (!qualitativeStateSets.maybeStates.empty()) { + // In this case we have have to compute the remaining probabilities. + + // Obtain proper hint information either from the provided hint or from requirements of the solver. + SparseMdpHintType hintInformation = computeHints(storm::solver::EquationSystemType::UntilProbabilities, hint, goal.direction(), transitionMatrix, backwardTransitions, qualitativeStateSets.maybeStates, phiStates, qualitativeStateSets.statesWithProbability1, minMaxLinearEquationSolverFactory); + + // Declare the components of the equation system we will solve. + storm::storage::SparseMatrix submatrix; + std::vector b; + + // If the hint information tells us that we have to eliminate MECs, we do so now. + boost::optional> ecInformation; + if (hintInformation.getEliminateEndComponents()) { + ecInformation = computeFixedPointSystemUntilProbabilitiesEliminateEndComponents(transitionMatrix, backwardTransitions, qualitativeStateSets, submatrix, b); + + // Make sure we are not supposed to produce a scheduler if we actually eliminate end components. + STORM_LOG_THROW(!ecInformation || !ecInformation.get().eliminatedEndComponents || !produceScheduler, storm::exceptions::NotSupportedException, "Producing schedulers is not supported if end-components need to be eliminated for the solver."); + } else { + // Otherwise, we compute the standard equations. + computeFixedPointSystemUntilProbabilities(transitionMatrix, qualitativeStateSets, submatrix, b); + } + + // Now compute the results for the maybe states. + goal.restrictRelevantValues(qualitativeStateSets.maybeStates); + MaybeStateResult resultForMaybeStates = computeValuesForMaybeStates(std::move(goal), std::move(submatrix), b, produceScheduler, minMaxLinearEquationSolverFactory, hintInformation); + + // If we eliminated end components, we need to extract the result differently. + if (ecInformation && ecInformation.get().eliminatedEndComponents) { + setResultValuesWrtEndComponents(ecInformation.get(), result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); + } else { + // Set values of resulting vector according to result. + storm::utility::vector::setVectorValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); + } + + if (produceScheduler) { + extractSchedulerChoices(*scheduler, resultForMaybeStates.getScheduler(), qualitativeStateSets.maybeStates); + } + } } - } - template - MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeUntilProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) { - storm::solver::SolveGoal goal(dir); - return std::move(computeUntilProbabilities(goal, transitionMatrix, backwardTransitions, phiStates, psiStates, qualitative, produceScheduler, minMaxLinearEquationSolverFactory, hint)); + // Extend scheduler with choices for the states in the qualitative state sets. + if (produceScheduler) { + extendScheduler(*scheduler, goal, qualitativeStateSets, transitionMatrix, backwardTransitions, phiStates, psiStates); + } + + // Sanity check for created scheduler. + STORM_LOG_ASSERT((!produceScheduler && !scheduler) || (!scheduler->isPartialScheduler() && scheduler->isDeterministicScheduler() && scheduler->isMemorylessScheduler()), "Unexpected format of obtained scheduler."); + + // Return result. + return MDPSparseModelCheckingHelperReturnType(std::move(result), std::move(scheduler)); } - + template - std::vector SparseMdpPrctlHelper::computeGloballyProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, bool useMecBasedTechnique) { + std::vector SparseMdpPrctlHelper::computeGloballyProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, bool useMecBasedTechnique) { if (useMecBasedTechnique) { storm::storage::MaximalEndComponentDecomposition mecDecomposition(transitionMatrix, backwardTransitions, psiStates); storm::storage::BitVector statesInPsiMecs(transitionMatrix.getRowGroupCount()); @@ -345,9 +812,10 @@ namespace storm { } } - return std::move(computeUntilProbabilities(dir, transitionMatrix, backwardTransitions, psiStates, statesInPsiMecs, qualitative, false, minMaxLinearEquationSolverFactory).values); + return std::move(computeUntilProbabilities(std::move(goal), transitionMatrix, backwardTransitions, psiStates, statesInPsiMecs, qualitative, false, minMaxLinearEquationSolverFactory).values); } else { - std::vector result = computeUntilProbabilities(dir == OptimizationDirection::Minimize ? OptimizationDirection::Maximize : OptimizationDirection::Minimize, transitionMatrix, backwardTransitions, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), ~psiStates, qualitative, false, minMaxLinearEquationSolverFactory).values; + goal.oneMinus(); + std::vector result = computeUntilProbabilities(std::move(goal), transitionMatrix, backwardTransitions, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), ~psiStates, qualitative, false, minMaxLinearEquationSolverFactory).values; for (auto& element : result) { element = storm::utility::one() - element; } @@ -357,7 +825,7 @@ namespace storm { template template - std::vector SparseMdpPrctlHelper::computeInstantaneousRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { + std::vector SparseMdpPrctlHelper::computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { // Only compute the result if the model has a state-based reward this->getModel(). STORM_LOG_THROW(rewardModel.hasStateRewards(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); @@ -365,15 +833,15 @@ namespace storm { // Initialize result to state rewards of the this->getModel(). std::vector result(rewardModel.getStateRewardVector()); - std::unique_ptr> solver = minMaxLinearEquationSolverFactory.create(transitionMatrix); - solver->repeatedMultiply(dir, result, nullptr, stepCount); + std::unique_ptr> solver = storm::solver::configureMinMaxLinearEquationSolver(std::move(goal), minMaxLinearEquationSolverFactory, transitionMatrix); + solver->repeatedMultiply(result, nullptr, stepCount); return result; } template template - std::vector SparseMdpPrctlHelper::computeCumulativeRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { + std::vector SparseMdpPrctlHelper::computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { // Only compute the result if the model has at least one reward this->getModel(). STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); @@ -384,30 +852,18 @@ namespace storm { // Initialize result to the zero vector. std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); - std::unique_ptr> solver = minMaxLinearEquationSolverFactory.create(transitionMatrix); - solver->repeatedMultiply(dir, result, &totalRewardVector, stepBound); + std::unique_ptr> solver = storm::solver::configureMinMaxLinearEquationSolver(std::move(goal), minMaxLinearEquationSolverFactory, transitionMatrix); + solver->repeatedMultiply(result, &totalRewardVector, stepBound); return result; } template template - MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) { - // Only compute the result if the model has at least one reward this->getModel(). - STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); - return computeReachabilityRewardsHelper(storm::solver::SolveGoal(dir), transitionMatrix, backwardTransitions, - [&rewardModel] (uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { - return rewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); - }, - targetStates, qualitative, produceScheduler, minMaxLinearEquationSolverFactory, hint); - } - - template - template - MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) { + MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) { // Only compute the result if the model has at least one reward this->getModel(). STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); - return computeReachabilityRewardsHelper(goal, transitionMatrix, backwardTransitions, + return computeReachabilityRewardsHelper(std::move(goal), transitionMatrix, backwardTransitions, [&rewardModel] (uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { return rewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); }, @@ -416,10 +872,10 @@ namespace storm { #ifdef STORM_HAVE_CARL template - std::vector SparseMdpPrctlHelper::computeReachabilityRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& intervalRewardModel, bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { + std::vector SparseMdpPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& intervalRewardModel, bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { // Only compute the result if the reward model is not empty. STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); - return computeReachabilityRewardsHelper(storm::solver::SolveGoal(dir), transitionMatrix, backwardTransitions, \ + return computeReachabilityRewardsHelper(std::move(goal), transitionMatrix, backwardTransitions, \ [&] (uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { std::vector result; result.reserve(rowCount); @@ -433,37 +889,185 @@ namespace storm { } template<> - std::vector SparseMdpPrctlHelper::computeReachabilityRewards(OptimizationDirection, storm::storage::SparseMatrix const&, storm::storage::SparseMatrix const&, storm::models::sparse::StandardRewardModel const&, bool, storm::storage::BitVector const&, bool, storm::solver::MinMaxLinearEquationSolverFactory const&) { + std::vector SparseMdpPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal&&, storm::storage::SparseMatrix const&, storm::storage::SparseMatrix const&, storm::models::sparse::StandardRewardModel const&, bool, storm::storage::BitVector const&, bool, storm::solver::MinMaxLinearEquationSolverFactory const&) { STORM_LOG_THROW(false, storm::exceptions::IllegalFunctionCallException, "Computing reachability rewards is unsupported for this data type."); } #endif + struct QualitativeStateSetsReachabilityRewards { + storm::storage::BitVector maybeStates; + storm::storage::BitVector infinityStates; + }; + template - MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewardsHelper(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) { - - std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); - std::vector const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices(); - - // Determine which states have a reward that is infinity or less than infinity. - storm::storage::BitVector maybeStates, infinityStates; + QualitativeStateSetsReachabilityRewards getQualitativeStateSetsReachabilityRewardsFromHint(ModelCheckerHint const& hint, storm::storage::BitVector const& targetStates) { + QualitativeStateSetsReachabilityRewards result; + result.maybeStates = hint.template asExplicitModelCheckerHint().getMaybeStates(); + result.infinityStates = ~(result.maybeStates | targetStates); + return result; + } + + template + QualitativeStateSetsReachabilityRewards computeQualitativeStateSetsReachabilityRewards(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates) { + QualitativeStateSetsReachabilityRewards result; + storm::storage::BitVector trueStates(transitionMatrix.getRowGroupCount(), true); + if (goal.minimize()) { + result.infinityStates = storm::utility::graph::performProb1E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, trueStates, targetStates); + } else { + result.infinityStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, trueStates, targetStates); + } + result.infinityStates.complement(); + result.maybeStates = ~(targetStates | result.infinityStates); + return result; + } + + template + QualitativeStateSetsReachabilityRewards getQualitativeStateSetsReachabilityRewards(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, ModelCheckerHint const& hint) { if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint().getComputeOnlyMaybeStates()) { - maybeStates = hint.template asExplicitModelCheckerHint().getMaybeStates(); - infinityStates = ~(maybeStates | targetStates); + return getQualitativeStateSetsReachabilityRewardsFromHint(hint, targetStates); } else { - storm::storage::BitVector trueStates(transitionMatrix.getRowGroupCount(), true); - if (goal.minimize()) { - STORM_LOG_WARN("Results of reward computation may be too low, because of zero-reward loops."); - infinityStates = storm::utility::graph::performProb1E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, trueStates, targetStates); - } else { - infinityStates = storm::utility::graph::performProb1A(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, trueStates, targetStates); + return computeQualitativeStateSetsReachabilityRewards(goal, transitionMatrix, backwardTransitions, targetStates); + } + } + + template + void extendScheduler(storm::storage::Scheduler& scheduler, storm::solver::SolveGoal const& goal, QualitativeStateSetsReachabilityRewards const& qualitativeStateSets, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& targetStates) { + // Finally, if we need to produce a scheduler, we also need to figure out the parts of the scheduler for + // the states with reward infinity. Moreover, we have to set some arbitrary choice for the remaining states + // to obtain a fully defined scheduler. + if (!goal.minimize()) { + storm::utility::graph::computeSchedulerProb0E(qualitativeStateSets.infinityStates, transitionMatrix, scheduler); + } else { + for (auto const& state : qualitativeStateSets.infinityStates) { + scheduler.setChoice(0, state); } - infinityStates.complement(); - maybeStates = ~(targetStates | infinityStates); - STORM_LOG_INFO("Found " << infinityStates.getNumberOfSetBits() << " 'infinity' states."); - STORM_LOG_INFO("Found " << targetStates.getNumberOfSetBits() << " 'target' states."); - STORM_LOG_INFO("Found " << maybeStates.getNumberOfSetBits() << " 'maybe' states."); } - storm::utility::vector::setVectorValues(result, infinityStates, storm::utility::infinity()); + for (auto const& state : targetStates) { + scheduler.setChoice(0, state); + } + } + + template + void extractSchedulerChoices(storm::storage::Scheduler& scheduler, storm::storage::SparseMatrix const& transitionMatrix, std::vector const& subChoices, storm::storage::BitVector const& maybeStates, boost::optional const& selectedChoices) { + auto subChoiceIt = subChoices.begin(); + if (selectedChoices) { + for (auto maybeState : maybeStates) { + // find the rowindex that corresponds to the selected row of the submodel + uint_fast64_t firstRowIndex = transitionMatrix.getRowGroupIndices()[maybeState]; + uint_fast64_t selectedRowIndex = selectedChoices->getNextSetIndex(firstRowIndex); + for (uint_fast64_t choice = 0; choice < *subChoiceIt; ++choice) { + selectedRowIndex = selectedChoices->getNextSetIndex(selectedRowIndex + 1); + } + scheduler.setChoice(selectedRowIndex - firstRowIndex, maybeState); + ++subChoiceIt; + } + } else { + for (auto maybeState : maybeStates) { + scheduler.setChoice(*subChoiceIt, maybeState); + ++subChoiceIt; + } + } + assert(subChoiceIt == subChoices.end()); + } + + template + void computeFixedPointSystemReachabilityRewards(storm::storage::SparseMatrix const& transitionMatrix, QualitativeStateSetsReachabilityRewards const& qualitativeStateSets, storm::storage::BitVector const& targetStates, boost::optional const& selectedChoices, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, storm::storage::SparseMatrix& submatrix, std::vector& b, std::vector* oneStepTargetProbabilities = nullptr) { + // Remove rows and columns from the original transition probability matrix for states whose reward values are already known. + // If there are infinity states, we additionally have to remove choices of maybeState that lead to infinity. + if (qualitativeStateSets.infinityStates.empty()) { + submatrix = transitionMatrix.getSubmatrix(true, qualitativeStateSets.maybeStates, qualitativeStateSets.maybeStates, false); + b = totalStateRewardVectorGetter(submatrix.getRowCount(), transitionMatrix, qualitativeStateSets.maybeStates); + if (oneStepTargetProbabilities) { + (*oneStepTargetProbabilities) = transitionMatrix.getConstrainedRowGroupSumVector(qualitativeStateSets.maybeStates, targetStates); + } + } else { + submatrix = transitionMatrix.getSubmatrix(false, *selectedChoices, qualitativeStateSets.maybeStates, false); + b = totalStateRewardVectorGetter(transitionMatrix.getRowCount(), transitionMatrix, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true)); + storm::utility::vector::filterVectorInPlace(b, *selectedChoices); + if (oneStepTargetProbabilities) { + (*oneStepTargetProbabilities) = transitionMatrix.getConstrainedRowSumVector(*selectedChoices, targetStates); + } + } + } + + template + boost::optional> computeFixedPointSystemReachabilityRewardsEliminateEndComponents(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, QualitativeStateSetsReachabilityRewards const& qualitativeStateSets, storm::storage::BitVector const& targetStates, boost::optional const& selectedChoices, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, storm::storage::SparseMatrix& submatrix, std::vector& b, boost::optional>& oneStepTargetProbabilities) { + + // Start by computing the choices with reward 0, as we only want ECs within this fragment. + storm::storage::BitVector zeroRewardChoices(transitionMatrix.getRowCount()); + + // Get the rewards of all choices. + std::vector rewardVector = totalStateRewardVectorGetter(transitionMatrix.getRowCount(), transitionMatrix, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true)); + + uint64_t index = 0; + for (auto const& e : rewardVector) { + if (storm::utility::isZero(e)) { + zeroRewardChoices.set(index); + } + ++index; + } + + // Compute the states that have some zero reward choice. + storm::storage::BitVector candidateStates(qualitativeStateSets.maybeStates); + for (auto state : qualitativeStateSets.maybeStates) { + bool keepState = false; + + for (auto row = transitionMatrix.getRowGroupIndices()[state], rowEnd = transitionMatrix.getRowGroupIndices()[state + 1]; row < rowEnd; ++row) { + if (zeroRewardChoices.get(row)) { + keepState = true; + break; + } + } + + if (!keepState) { + candidateStates.set(state, false); + } + } + + bool doDecomposition = !candidateStates.empty(); + + storm::storage::MaximalEndComponentDecomposition endComponentDecomposition; + if (doDecomposition) { + // Then compute the states that are in MECs with zero reward. + endComponentDecomposition = storm::storage::MaximalEndComponentDecomposition(transitionMatrix, backwardTransitions, candidateStates, zeroRewardChoices); + } + + // Only do more work if there are actually end-components. + if (doDecomposition && !endComponentDecomposition.empty()) { + STORM_LOG_DEBUG("Eliminating " << endComponentDecomposition.size() << " ECs."); + return eliminateEndComponents(endComponentDecomposition, transitionMatrix, qualitativeStateSets.maybeStates, oneStepTargetProbabilities ? &targetStates : nullptr, selectedChoices ? &selectedChoices.get() : nullptr, &rewardVector, submatrix, oneStepTargetProbabilities ? &oneStepTargetProbabilities.get() : nullptr, &b); + } else { + STORM_LOG_DEBUG("Not eliminating ECs as there are none."); + computeFixedPointSystemReachabilityRewards(transitionMatrix, qualitativeStateSets, targetStates, selectedChoices, totalStateRewardVectorGetter, submatrix, b, oneStepTargetProbabilities ? &oneStepTargetProbabilities.get() : nullptr); + return boost::none; + } + } + + template + void computeUpperRewardBounds(SparseMdpHintType& hintInformation, storm::OptimizationDirection const& direction, storm::storage::SparseMatrix const& submatrix, std::vector const& choiceRewards, std::vector const& oneStepTargetProbabilities) { + + // For the min-case, we use DS-MPI, for the max-case variant 2 of the Baier et al. paper (CAV'17). + if (direction == storm::OptimizationDirection::Minimize) { + DsMpiMdpUpperRewardBoundsComputer dsmpi(submatrix, choiceRewards, oneStepTargetProbabilities); + hintInformation.upperResultBounds = dsmpi.computeUpperBounds(); + } else { + BaierUpperRewardBoundsComputer baier(submatrix, choiceRewards, oneStepTargetProbabilities); + hintInformation.upperResultBound = baier.computeUpperBound(); + } + } + + template + MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewardsHelper(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint) { + + // Prepare resulting vector. + std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); + + // Determine which states have a reward that is infinity or less than infinity. + QualitativeStateSetsReachabilityRewards qualitativeStateSets = getQualitativeStateSetsReachabilityRewards(goal, transitionMatrix, backwardTransitions, targetStates, hint); + + STORM_LOG_INFO("Preprocessing: " << qualitativeStateSets.infinityStates.getNumberOfSetBits() << " states with reward infinity, " << targetStates.getNumberOfSetBits() << " target states (" << qualitativeStateSets.maybeStates.getNumberOfSetBits() << " states remaining)."); + + storm::utility::vector::setVectorValues(result, qualitativeStateSets.infinityStates, storm::utility::infinity()); // If requested, we will produce a scheduler. std::unique_ptr> scheduler; @@ -476,84 +1080,80 @@ namespace storm { STORM_LOG_INFO("The rewards for the initial states were determined in a preprocessing step. No exact rewards were computed."); // Set the values for all maybe-states to 1 to indicate that their reward values // are neither 0 nor infinity. - storm::utility::vector::setVectorValues(result, maybeStates, storm::utility::one()); + storm::utility::vector::setVectorValues(result, qualitativeStateSets.maybeStates, storm::utility::one()); } else { - if (!maybeStates.empty()) { + if (!qualitativeStateSets.maybeStates.empty()) { // In this case we have to compute the reward values for the remaining states. + + // Store the choices that lead to non-infinity values. If none, all choices im maybe states can be selected. + boost::optional selectedChoices; + if (!qualitativeStateSets.infinityStates.empty()) { + selectedChoices = transitionMatrix.getRowFilter(qualitativeStateSets.maybeStates, ~qualitativeStateSets.infinityStates); + } + + // Obtain proper hint information either from the provided hint or from requirements of the solver. + SparseMdpHintType hintInformation = computeHints(storm::solver::EquationSystemType::ReachabilityRewards, hint, goal.direction(), transitionMatrix, backwardTransitions, qualitativeStateSets.maybeStates, ~targetStates, targetStates, minMaxLinearEquationSolverFactory, selectedChoices); - // Prepare matrix and vector for the equation system. + // Declare the components of the equation system we will solve. storm::storage::SparseMatrix submatrix; std::vector b; - // Remove rows and columns from the original transition probability matrix for states whose reward values are already known. - // If there are infinity states, we additionaly have to remove choices of maybeState that lead to infinity - boost::optional selectedChoices; // if not given, all maybeState choices are selected - if (infinityStates.empty()) { - submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false); - b = totalStateRewardVectorGetter(submatrix.getRowCount(), transitionMatrix, maybeStates); + + // If we need to compute upper bounds on the reward values, we need the one step probabilities + // to a target state. + boost::optional> oneStepTargetProbabilities; + if (hintInformation.getComputeUpperBounds()) { + oneStepTargetProbabilities = std::vector(); + } + + // If the hint information tells us that we have to eliminate MECs, we do so now. + boost::optional> ecInformation; + if (hintInformation.getEliminateEndComponents()) { + ecInformation = computeFixedPointSystemReachabilityRewardsEliminateEndComponents(transitionMatrix, backwardTransitions, qualitativeStateSets, targetStates, selectedChoices, totalStateRewardVectorGetter, submatrix, b, oneStepTargetProbabilities); + + // Make sure we are not supposed to produce a scheduler if we actually eliminate end components. + STORM_LOG_THROW(!ecInformation || !ecInformation.get().eliminatedEndComponents || !produceScheduler, storm::exceptions::NotSupportedException, "Producing schedulers is not supported if end-components need to be eliminated for the solver."); } else { - selectedChoices = transitionMatrix.getRowFilter(maybeStates, ~infinityStates); - submatrix = transitionMatrix.getSubmatrix(false, *selectedChoices, maybeStates, false); - b = totalStateRewardVectorGetter(transitionMatrix.getRowCount(), transitionMatrix, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true)); - storm::utility::vector::filterVectorInPlace(b, *selectedChoices); + // Otherwise, we compute the standard equations. + computeFixedPointSystemReachabilityRewards(transitionMatrix, qualitativeStateSets, targetStates, selectedChoices, totalStateRewardVectorGetter, submatrix, b, oneStepTargetProbabilities ? &oneStepTargetProbabilities.get() : nullptr); } - // obtain hint information if possible - bool skipEcWithinMaybeStatesCheck = !goal.minimize() || (hint.isExplicitModelCheckerHint() && hint.asExplicitModelCheckerHint().getNoEndComponentsInMaybeStates()); - std::pair>, boost::optional>> hintInformation = extractHintInformationForMaybeStates(transitionMatrix, backwardTransitions, maybeStates, selectedChoices, hint, skipEcWithinMaybeStatesCheck); + // If we need to compute upper bounds, do so now. + if (hintInformation.getComputeUpperBounds()) { + STORM_LOG_ASSERT(oneStepTargetProbabilities, "Expecting one step target probability vector to be available."); + computeUpperRewardBounds(hintInformation, goal.direction(), submatrix, b, oneStepTargetProbabilities.get()); + } - // Now compute the results for the maybeStates - std::pair, boost::optional>> resultForMaybeStates = computeValuesOnlyMaybeStates(goal, submatrix, b, produceScheduler, minMaxLinearEquationSolverFactory, std::move(hintInformation.first), std::move(hintInformation.second), storm::utility::zero()); + // Now compute the results for the maybe states. + goal.restrictRelevantValues(qualitativeStateSets.maybeStates); + MaybeStateResult resultForMaybeStates = computeValuesForMaybeStates(std::move(goal), std::move(submatrix), b, produceScheduler, minMaxLinearEquationSolverFactory, hintInformation); - // Set values of resulting vector according to result. - storm::utility::vector::setVectorValues(result, maybeStates, resultForMaybeStates.first); + // If we eliminated end components, we need to extract the result differently. + if (ecInformation && ecInformation.get().eliminatedEndComponents) { + setResultValuesWrtEndComponents(ecInformation.get(), result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); + } else { + // Set values of resulting vector according to result. + storm::utility::vector::setVectorValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); + } if (produceScheduler) { - std::vector const& subChoices = resultForMaybeStates.second.get(); - auto subChoiceIt = subChoices.begin(); - if (selectedChoices) { - for (auto maybeState : maybeStates) { - // find the rowindex that corresponds to the selected row of the submodel - uint_fast64_t firstRowIndex = transitionMatrix.getRowGroupIndices()[maybeState]; - uint_fast64_t selectedRowIndex = selectedChoices->getNextSetIndex(firstRowIndex); - for (uint_fast64_t choice = 0; choice < *subChoiceIt; ++choice) { - selectedRowIndex = selectedChoices->getNextSetIndex(selectedRowIndex + 1); - } - scheduler->setChoice(selectedRowIndex - firstRowIndex, maybeState); - ++subChoiceIt; - } - } else { - for (auto maybeState : maybeStates) { - scheduler->setChoice(*subChoiceIt, maybeState); - ++subChoiceIt; - } - } - assert(subChoiceIt == subChoices.end()); + extractSchedulerChoices(*scheduler, transitionMatrix, resultForMaybeStates.getScheduler(), qualitativeStateSets.maybeStates, selectedChoices); } } } - // Finally, if we need to produce a scheduler, we also need to figure out the parts of the scheduler for - // the states with reward infinity. Moreover, we have to set some arbitrary choice for the remaining states - // to obtain a fully defined scheduler + // Extend scheduler with choices for the states in the qualitative state sets. if (produceScheduler) { - if (!goal.minimize()) { - storm::utility::graph::computeSchedulerProb0E(infinityStates, transitionMatrix, *scheduler); - } else { - for (auto const& state : infinityStates) { - scheduler->setChoice(0, state); - } - } - for (auto const& state : targetStates) { - scheduler->setChoice(0, state); - } + extendScheduler(*scheduler, goal, qualitativeStateSets, transitionMatrix, targetStates); } + + // Sanity check for created scheduler. STORM_LOG_ASSERT((!produceScheduler && !scheduler) || (!scheduler->isPartialScheduler() && scheduler->isDeterministicScheduler() && scheduler->isMemorylessScheduler()), "Unexpected format of obtained scheduler."); return MDPSparseModelCheckingHelperReturnType(std::move(result), std::move(scheduler)); } template - std::vector SparseMdpPrctlHelper::computeLongRunAverageProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { + std::vector SparseMdpPrctlHelper::computeLongRunAverageProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { // If there are no goal states, we avoid the computation and directly return zero. if (psiStates.empty()) { @@ -570,12 +1170,12 @@ namespace storm { std::vector stateRewards(psiStates.size(), storm::utility::zero()); storm::utility::vector::setVectorValues(stateRewards, psiStates, storm::utility::one()); storm::models::sparse::StandardRewardModel rewardModel(std::move(stateRewards)); - return computeLongRunAverageRewards(dir, transitionMatrix, backwardTransitions, rewardModel, minMaxLinearEquationSolverFactory); + return computeLongRunAverageRewards(std::move(goal), transitionMatrix, backwardTransitions, rewardModel, minMaxLinearEquationSolverFactory); } template template - std::vector SparseMdpPrctlHelper::computeLongRunAverageRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { + std::vector SparseMdpPrctlHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { uint64_t numberOfStates = transitionMatrix.getRowGroupCount(); @@ -594,7 +1194,7 @@ namespace storm { for (uint_fast64_t currentMecIndex = 0; currentMecIndex < mecDecomposition.size(); ++currentMecIndex) { storm::storage::MaximalEndComponent const& mec = mecDecomposition[currentMecIndex]; - lraValuesForEndComponents[currentMecIndex] = computeLraForMaximalEndComponent(dir, transitionMatrix, rewardModel, mec, minMaxLinearEquationSolverFactory); + lraValuesForEndComponents[currentMecIndex] = computeLraForMaximalEndComponent(goal.direction(), transitionMatrix, rewardModel, mec, minMaxLinearEquationSolverFactory); // Gather information for later use. for (auto const& stateChoicesPair : mec) { @@ -699,9 +1299,15 @@ namespace storm { // Finalize the matrix and solve the corresponding system of equations. storm::storage::SparseMatrix sspMatrix = sspMatrixBuilder.build(currentChoice, numberOfSspStates, numberOfSspStates); + // Check for requirements of the solver. + storm::solver::MinMaxLinearEquationSolverRequirements requirements = minMaxLinearEquationSolverFactory.getRequirements(storm::solver::EquationSystemType::StochasticShortestPath); + STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Cannot establish requirements for solver."); + std::vector sspResult(numberOfSspStates); - std::unique_ptr> solver = minMaxLinearEquationSolverFactory.create(std::move(sspMatrix)); - solver->solveEquations(dir, sspResult, b); + goal.restrictRelevantValues(statesNotContainedInAnyMec); + std::unique_ptr> solver = storm::solver::configureMinMaxLinearEquationSolver(std::move(goal), minMaxLinearEquationSolverFactory, sspMatrix); + solver->setRequirementsChecked(); + solver->solveEquations(sspResult, b); // Prepare result vector. std::vector result(numberOfStates, zero); @@ -812,6 +1418,7 @@ namespace storm { ValueType precision = storm::utility::convertNumber(storm::settings::getModule().getPrecision()); std::vector x(mecTransitions.getRowGroupCount(), storm::utility::zero()); std::vector xPrime = x; + auto solver = minMaxLinearEquationSolverFactory.create(std::move(mecTransitions)); solver->setCachingEnabled(true); ValueType maxDiff, minDiff; @@ -886,12 +1493,14 @@ namespace storm { } template - std::unique_ptr SparseMdpPrctlHelper::computeConditionalProbabilities(OptimizationDirection dir, storm::storage::sparse::state_type initialState, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { + std::unique_ptr SparseMdpPrctlHelper::computeConditionalProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { + + std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); // For the max-case, we can simply take the given target states. For the min-case, however, we need to // find the MECs of non-target states and make them the new target states. storm::storage::BitVector fixedTargetStates; - if (dir == OptimizationDirection::Maximize) { + if (!goal.minimize()) { fixedTargetStates = targetStates; } else { fixedTargetStates = storm::storage::BitVector(targetStates.size()); @@ -903,19 +1512,37 @@ namespace storm { } } + storm::storage::BitVector allStates(fixedTargetStates.size(), true); + + // Extend the target states by computing all states that have probability 1 to go to a target state + // under *all* schedulers. + fixedTargetStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, fixedTargetStates); + // We solve the max-case and later adjust the result if the optimization direction was to minimize. - storm::storage::BitVector initialStatesBitVector(transitionMatrix.getRowGroupCount()); - initialStatesBitVector.set(initialState); + storm::storage::BitVector initialStatesBitVector = goal.relevantValues(); + STORM_LOG_THROW(initialStatesBitVector.getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, "Computing conditional probabilities in MDPs is only supported for models with exactly one initial state."); + storm::storage::sparse::state_type initialState = *initialStatesBitVector.begin(); - storm::storage::BitVector allStates(initialStatesBitVector.size(), true); - std::vector conditionProbabilities = std::move(computeUntilProbabilities(OptimizationDirection::Maximize, transitionMatrix, backwardTransitions, allStates, conditionStates, false, false, minMaxLinearEquationSolverFactory).values); + // Extend the condition states by computing all states that have probability 1 to go to a condition state + // under *all* schedulers. + storm::storage::BitVector extendedConditionStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates); + + STORM_LOG_DEBUG("Computing probabilities to satisfy condition."); + std::chrono::high_resolution_clock::time_point conditionStart = std::chrono::high_resolution_clock::now(); + std::vector conditionProbabilities = std::move(computeUntilProbabilities(OptimizationDirection::Maximize, transitionMatrix, backwardTransitions, allStates, extendedConditionStates, false, false, minMaxLinearEquationSolverFactory).values); + std::chrono::high_resolution_clock::time_point conditionEnd = std::chrono::high_resolution_clock::now(); + STORM_LOG_DEBUG("Computed probabilities to satisfy for condition in " << std::chrono::duration_cast(conditionEnd - conditionStart).count() << "ms."); // If the conditional probability is undefined for the initial state, we return directly. if (storm::utility::isZero(conditionProbabilities[initialState])) { return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, storm::utility::infinity())); } + STORM_LOG_DEBUG("Computing probabilities to reach target."); + std::chrono::high_resolution_clock::time_point targetStart = std::chrono::high_resolution_clock::now(); std::vector targetProbabilities = std::move(computeUntilProbabilities(OptimizationDirection::Maximize, transitionMatrix, backwardTransitions, allStates, fixedTargetStates, false, false, minMaxLinearEquationSolverFactory).values); + std::chrono::high_resolution_clock::time_point targetEnd = std::chrono::high_resolution_clock::now(); + STORM_LOG_DEBUG("Computed probabilities to reach target in " << std::chrono::duration_cast(targetEnd - targetStart).count() << "ms."); storm::storage::BitVector statesWithProbabilityGreater0E(transitionMatrix.getRowGroupCount(), true); storm::storage::sparse::state_type state = 0; @@ -927,10 +1554,13 @@ namespace storm { } // Determine those states that need to be equipped with a restart mechanism. - storm::storage::BitVector problematicStates = storm::utility::graph::performProb0E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates | fixedTargetStates); + STORM_LOG_DEBUG("Computing problematic states."); + storm::storage::BitVector pureResetStates = storm::utility::graph::performProb0A(backwardTransitions, allStates, extendedConditionStates); + storm::storage::BitVector problematicStates = storm::utility::graph::performProb0E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, extendedConditionStates | fixedTargetStates); // Otherwise, we build the transformed MDP. - storm::storage::BitVector relevantStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStatesBitVector, allStates, conditionStates | fixedTargetStates); + storm::storage::BitVector relevantStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStatesBitVector, allStates, extendedConditionStates | fixedTargetStates | pureResetStates); + STORM_LOG_TRACE("Found " << relevantStates.getNumberOfSetBits() << " relevant states for conditional probability computation."); std::vector numberOfStatesBeforeRelevantStates = relevantStates.getNumberOfSetBitsBeforeIndices(); storm::storage::sparse::state_type newGoalState = relevantStates.getNumberOfSetBits(); storm::storage::sparse::state_type newStopState = newGoalState + 1; @@ -942,17 +1572,24 @@ namespace storm { for (auto state : relevantStates) { builder.newRowGroup(currentRow); if (fixedTargetStates.get(state)) { - builder.addNextValue(currentRow, newGoalState, conditionProbabilities[state]); if (!storm::utility::isZero(conditionProbabilities[state])) { + builder.addNextValue(currentRow, newGoalState, conditionProbabilities[state]); + } + if (!storm::utility::isOne(conditionProbabilities[state])) { builder.addNextValue(currentRow, newFailState, storm::utility::one() - conditionProbabilities[state]); } ++currentRow; - } else if (conditionStates.get(state)) { - builder.addNextValue(currentRow, newGoalState, targetProbabilities[state]); + } else if (extendedConditionStates.get(state)) { if (!storm::utility::isZero(targetProbabilities[state])) { + builder.addNextValue(currentRow, newGoalState, targetProbabilities[state]); + } + if (!storm::utility::isOne(targetProbabilities[state])) { builder.addNextValue(currentRow, newStopState, storm::utility::one() - targetProbabilities[state]); } ++currentRow; + } else if (pureResetStates.get(state)) { + builder.addNextValue(currentRow, numberOfStatesBeforeRelevantStates[initialState], storm::utility::one()); + ++currentRow; } else { for (uint_fast64_t row = transitionMatrix.getRowGroupIndices()[state]; row < transitionMatrix.getRowGroupIndices()[state + 1]; ++row) { for (auto const& successorEntry : transitionMatrix.getRow(row)) { @@ -978,33 +1615,45 @@ namespace storm { builder.addNextValue(currentRow, numberOfStatesBeforeRelevantStates[initialState], storm::utility::one()); ++currentRow; + std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); + STORM_LOG_DEBUG("Computed transformed model in " << std::chrono::duration_cast(end - start).count() << "ms."); + // Finally, build the matrix and dispatch the query as a reachability query. + STORM_LOG_DEBUG("Computing conditional probabilties."); storm::storage::BitVector newGoalStates(newFailState + 1); newGoalStates.set(newGoalState); storm::storage::SparseMatrix newTransitionMatrix = builder.build(); + STORM_LOG_DEBUG("Transformed model has " << newTransitionMatrix.getRowGroupCount() << " states and " << newTransitionMatrix.getNonzeroEntryCount() << " transitions."); storm::storage::SparseMatrix newBackwardTransitions = newTransitionMatrix.transpose(true); - std::vector goalProbabilities = std::move(computeUntilProbabilities(OptimizationDirection::Maximize, newTransitionMatrix, newBackwardTransitions, storm::storage::BitVector(newFailState + 1, true), newGoalStates, false, false, minMaxLinearEquationSolverFactory).values); + + storm::solver::OptimizationDirection dir = goal.direction(); + if (goal.minimize()) { + goal.oneMinus(); + } + + std::chrono::high_resolution_clock::time_point conditionalStart = std::chrono::high_resolution_clock::now(); + std::vector goalProbabilities = std::move(computeUntilProbabilities(std::move(goal), newTransitionMatrix, newBackwardTransitions, storm::storage::BitVector(newFailState + 1, true), newGoalStates, false, false, minMaxLinearEquationSolverFactory).values); + std::chrono::high_resolution_clock::time_point conditionalEnd = std::chrono::high_resolution_clock::now(); + STORM_LOG_DEBUG("Computed conditional probabilities in transformed model in " << std::chrono::duration_cast(conditionalEnd - conditionalStart).count() << "ms."); return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, dir == OptimizationDirection::Maximize ? goalProbabilities[numberOfStatesBeforeRelevantStates[initialState]] : storm::utility::one() - goalProbabilities[numberOfStatesBeforeRelevantStates[initialState]])); } template class SparseMdpPrctlHelper; - template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepCount, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); - template std::vector SparseMdpPrctlHelper::computeCumulativeRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); - template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint); - template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint); - template std::vector SparseMdpPrctlHelper::computeLongRunAverageRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepCount, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + template std::vector SparseMdpPrctlHelper::computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint); + template std::vector SparseMdpPrctlHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); template double SparseMdpPrctlHelper::computeLraForMaximalEndComponent(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::MaximalEndComponent const& mec, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); template double SparseMdpPrctlHelper::computeLraForMaximalEndComponentVI(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::MaximalEndComponent const& mec, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); template double SparseMdpPrctlHelper::computeLraForMaximalEndComponentLP(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::MaximalEndComponent const& mec); #ifdef STORM_HAVE_CARL template class SparseMdpPrctlHelper; - template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepCount, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); - template std::vector SparseMdpPrctlHelper::computeCumulativeRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); - template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint); - template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint); - template std::vector SparseMdpPrctlHelper::computeLongRunAverageRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepCount, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + template std::vector SparseMdpPrctlHelper::computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper::computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint); + template std::vector SparseMdpPrctlHelper::computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); template storm::RationalNumber SparseMdpPrctlHelper::computeLraForMaximalEndComponent(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::MaximalEndComponent const& mec, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); template storm::RationalNumber SparseMdpPrctlHelper::computeLraForMaximalEndComponentVI(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::MaximalEndComponent const& mec, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); template storm::RationalNumber SparseMdpPrctlHelper::computeLraForMaximalEndComponentLP(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::MaximalEndComponent const& mec); diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h index 89505d192..7a14384f8 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h @@ -34,48 +34,39 @@ namespace storm { template class SparseMdpPrctlHelper { public: - static std::vector computeStepBoundedUntilProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); - + static std::vector computeStepBoundedUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); + static std::map computeNonTrivialBoundedUntilProbabilities(OptimizationDirection dir, storm::modelchecker::multiobjective::MultiDimensionalRewardUnfolding& rewardUnfolding, storm::storage::BitVector const& initialStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); static std::vector computeNextProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& nextStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); - static MDPSparseModelCheckingHelperReturnType computeUntilProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); - - static std::pair>, boost::optional>> extractHintInformationForMaybeStates(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& maybeStates, boost::optional const& selectedChoices, ModelCheckerHint const& hint, bool skipECWithinMaybeStatesCheck); - - static std::pair, boost::optional>> computeValuesOnlyMaybeStates(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& submatrix, std::vector const& b, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, boost::optional>&& hintValues = boost::none, boost::optional>&& hintChoices = boost::none, boost::optional const& lowerResultBound = boost::none, boost::optional const& upperResultBound = boost::none); + static MDPSparseModelCheckingHelperReturnType computeUntilProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); - static MDPSparseModelCheckingHelperReturnType computeUntilProbabilities(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); - - static std::vector computeGloballyProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, bool useMecBasedTechnique = false); + static std::vector computeGloballyProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, bool useMecBasedTechnique = false); template - static std::vector computeInstantaneousRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeInstantaneousRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); template - static std::vector computeCumulativeRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeCumulativeRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); template - static MDPSparseModelCheckingHelperReturnType computeReachabilityRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); + static MDPSparseModelCheckingHelperReturnType computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); - template - static MDPSparseModelCheckingHelperReturnType computeReachabilityRewards(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); - #ifdef STORM_HAVE_CARL - static std::vector computeReachabilityRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& intervalRewardModel, bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeReachabilityRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::models::sparse::StandardRewardModel const& intervalRewardModel, bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); #endif - static std::vector computeLongRunAverageProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeLongRunAverageProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); template - static std::vector computeLongRunAverageRewards(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeLongRunAverageRewards(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, RewardModelType const& rewardModel, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); - static std::unique_ptr computeConditionalProbabilities(OptimizationDirection dir, storm::storage::sparse::state_type initialState, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::unique_ptr computeConditionalProbabilities(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); private: - static MDPSparseModelCheckingHelperReturnType computeReachabilityRewardsHelper(storm::solver::SolveGoal const& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); + static MDPSparseModelCheckingHelperReturnType computeReachabilityRewardsHelper(storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory, ModelCheckerHint const& hint = ModelCheckerHint()); template static ValueType computeLraForMaximalEndComponent(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, storm::storage::MaximalEndComponent const& mec, storm::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); diff --git a/src/storm/modelchecker/prctl/helper/SymbolicDtmcPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SymbolicDtmcPrctlHelper.cpp index c54d15b92..cf8019aea 100644 --- a/src/storm/modelchecker/prctl/helper/SymbolicDtmcPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SymbolicDtmcPrctlHelper.cpp @@ -25,10 +25,7 @@ namespace storm { std::pair, storm::dd::Bdd> statesWithProbability01 = storm::utility::graph::performProb01(model, transitionMatrix, phiStates, psiStates); storm::dd::Bdd maybeStates = !statesWithProbability01.first && !statesWithProbability01.second && model.getReachableStates(); - // Perform some logging. - STORM_LOG_INFO("Found " << statesWithProbability01.first.getNonZeroCount() << " 'no' states."); - STORM_LOG_INFO("Found " << statesWithProbability01.second.getNonZeroCount() << " 'yes' states."); - STORM_LOG_INFO("Found " << maybeStates.getNonZeroCount() << " 'maybe' states."); + STORM_LOG_INFO("Preprocessing: " << statesWithProbability01.first.getNonZeroCount() << " states with probability 1, " << statesWithProbability01.second.getNonZeroCount() << " with probability 0 (" << maybeStates.getNonZeroCount() << " states remaining)."); // Check whether we need to compute exact probabilities for some states. if (qualitative) { @@ -146,9 +143,8 @@ namespace storm { storm::dd::Bdd infinityStates = storm::utility::graph::performProb1(model, transitionMatrix.notZero(), model.getReachableStates(), targetStates); infinityStates = !infinityStates && model.getReachableStates(); storm::dd::Bdd maybeStates = (!targetStates && !infinityStates) && model.getReachableStates(); - STORM_LOG_INFO("Found " << infinityStates.getNonZeroCount() << " 'infinity' states."); - STORM_LOG_INFO("Found " << targetStates.getNonZeroCount() << " 'target' states."); - STORM_LOG_INFO("Found " << maybeStates.getNonZeroCount() << " 'maybe' states."); + + STORM_LOG_INFO("Preprocessing: " << infinityStates.getNonZeroCount() << " states with reward infinity, " << targetStates.getNonZeroCount() << " target states (" << maybeStates.getNonZeroCount() << " states remaining)."); // Check whether we need to compute exact rewards for some states. if (qualitative) { diff --git a/src/storm/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp index 74a52cf90..bca6bec0f 100644 --- a/src/storm/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp @@ -9,7 +9,6 @@ #include "storm/utility/graph.h" #include "storm/utility/constants.h" - #include "storm/models/symbolic/StandardRewardModel.h" #include "storm/modelchecker/results/SymbolicQualitativeCheckResult.h" @@ -17,11 +16,26 @@ #include "storm/exceptions/InvalidPropertyException.h" #include "storm/exceptions/InvalidArgumentException.h" +#include "storm/exceptions/UncheckedRequirementException.h" namespace storm { namespace modelchecker { namespace helper { + template + storm::dd::Bdd computeValidSchedulerHint(storm::solver::EquationSystemType const& type, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& maybeStates, storm::dd::Bdd const& targetStates) { + + storm::dd::Bdd result; + + if (type == storm::solver::EquationSystemType::UntilProbabilities) { + result = storm::utility::graph::computeSchedulerProbGreater0E(model, transitionMatrix.notZero(), maybeStates, targetStates); + } else if (type == storm::solver::EquationSystemType::ReachabilityRewards) { + result = storm::utility::graph::computeSchedulerProb1E(model, transitionMatrix.notZero(), maybeStates, targetStates, maybeStates || targetStates); + } + + return result; + } + template std::unique_ptr SymbolicMdpPrctlHelper::computeUntilProbabilities(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& phiStates, storm::dd::Bdd const& psiStates, bool qualitative, storm::solver::SymbolicGeneralMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { // We need to identify the states which have to be taken out of the matrix, i.e. all states that have @@ -35,10 +49,7 @@ namespace storm { storm::dd::Bdd maybeStates = !statesWithProbability01.first && !statesWithProbability01.second && model.getReachableStates(); - // Perform some logging. - STORM_LOG_INFO("Found " << statesWithProbability01.first.getNonZeroCount() << " 'no' states."); - STORM_LOG_INFO("Found " << statesWithProbability01.second.getNonZeroCount() << " 'yes' states."); - STORM_LOG_INFO("Found " << maybeStates.getNonZeroCount() << " 'maybe' states."); + STORM_LOG_INFO("Preprocessing: " << statesWithProbability01.first.getNonZeroCount() << " states with probability 1, " << statesWithProbability01.second.getNonZeroCount() << " with probability 0 (" << maybeStates.getNonZeroCount() << " states remaining)."); // Check whether we need to compute exact probabilities for some states. if (qualitative) { @@ -66,7 +77,24 @@ namespace storm { // Now solve the resulting equation system. std::unique_ptr> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getIllegalMask() && maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); - storm::dd::Add result = solver->solveEquations(dir == OptimizationDirection::Minimize, model.getManager().template getAddZero(), subvector); + + // Check requirements of solver. + storm::solver::MinMaxLinearEquationSolverRequirements requirements = solver->getRequirements(storm::solver::EquationSystemType::UntilProbabilities, dir); + boost::optional> initialScheduler; + if (!requirements.empty()) { + if (requirements.requires(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler)) { + STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it."); + initialScheduler = computeValidSchedulerHint(storm::solver::EquationSystemType::UntilProbabilities, model, transitionMatrix, maybeStates, statesWithProbability01.second); + requirements.clearValidInitialScheduler(); + } + STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Could not establish requirements of solver."); + } + if (initialScheduler) { + solver->setInitialScheduler(initialScheduler.get()); + } + solver->setRequirementsChecked(); + + storm::dd::Add result = solver->solveEquations(dir, model.getManager().template getAddZero(), subvector); return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), statesWithProbability01.second.template toAdd() + result)); } else { @@ -123,7 +151,7 @@ namespace storm { submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); std::unique_ptr> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getIllegalMask() && maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); - storm::dd::Add result = solver->multiply(dir == OptimizationDirection::Minimize, model.getManager().template getAddZero(), &subvector, stepBound); + storm::dd::Add result = solver->multiply(dir, model.getManager().template getAddZero(), &subvector, stepBound); return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), psiStates.template toAdd() + result)); } else { @@ -138,7 +166,7 @@ namespace storm { // Perform the matrix-vector multiplication. std::unique_ptr> solver = linearEquationSolverFactory.create(transitionMatrix, model.getReachableStates(), model.getIllegalMask(), model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); - storm::dd::Add result = solver->multiply(dir == OptimizationDirection::Minimize, rewardModel.getStateRewardVector(), nullptr, stepBound); + storm::dd::Add result = solver->multiply(dir, rewardModel.getStateRewardVector(), nullptr, stepBound); return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), result)); } @@ -153,7 +181,7 @@ namespace storm { // Perform the matrix-vector multiplication. std::unique_ptr> solver = linearEquationSolverFactory.create(model.getTransitionMatrix(), model.getReachableStates(), model.getIllegalMask(), model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); - storm::dd::Add result = solver->multiply(dir == OptimizationDirection::Minimize, model.getManager().template getAddZero(), &totalRewardVector, stepBound); + storm::dd::Add result = solver->multiply(dir, model.getManager().template getAddZero(), &totalRewardVector, stepBound); return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), result)); } @@ -168,7 +196,6 @@ namespace storm { storm::dd::Bdd infinityStates; storm::dd::Bdd transitionMatrixBdd = transitionMatrix.notZero(); if (dir == OptimizationDirection::Minimize) { - STORM_LOG_WARN("Results of reward computation may be too low, because of zero-reward loops."); infinityStates = storm::utility::graph::performProb1E(model, transitionMatrixBdd, model.getReachableStates(), targetStates, storm::utility::graph::performProbGreater0E(model, transitionMatrixBdd, model.getReachableStates(), targetStates)); } else { infinityStates = storm::utility::graph::performProb1A(model, transitionMatrixBdd, targetStates, storm::utility::graph::performProbGreater0A(model, transitionMatrixBdd, model.getReachableStates(), targetStates)); @@ -176,10 +203,9 @@ namespace storm { infinityStates = !infinityStates && model.getReachableStates(); storm::dd::Bdd maybeStates = (!targetStates && !infinityStates) && model.getReachableStates(); - STORM_LOG_INFO("Found " << infinityStates.getNonZeroCount() << " 'infinity' states."); - STORM_LOG_INFO("Found " << targetStates.getNonZeroCount() << " 'target' states."); - STORM_LOG_INFO("Found " << maybeStates.getNonZeroCount() << " 'maybe' states."); + STORM_LOG_INFO("Preprocessing: " << infinityStates.getNonZeroCount() << " states with reward infinity, " << targetStates.getNonZeroCount() << " target states (" << maybeStates.getNonZeroCount() << " states remaining)."); + // Check whether we need to compute exact rewards for some states. if (qualitative) { // Set the values for all maybe-states to 1 to indicate that their reward values @@ -208,7 +234,24 @@ namespace storm { // Now solve the resulting equation system. std::unique_ptr> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getIllegalMask() && maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); - storm::dd::Add result = solver->solveEquations(dir == OptimizationDirection::Minimize, model.getManager().template getAddZero(), subvector); + + // Check requirements of solver. + storm::solver::MinMaxLinearEquationSolverRequirements requirements = solver->getRequirements(storm::solver::EquationSystemType::ReachabilityRewards, dir); + boost::optional> initialScheduler; + if (!requirements.empty()) { + if (requirements.requires(storm::solver::MinMaxLinearEquationSolverRequirements::Element::ValidInitialScheduler)) { + STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it."); + initialScheduler = computeValidSchedulerHint(storm::solver::EquationSystemType::ReachabilityRewards, model, transitionMatrix, maybeStates, targetStates); + requirements.clearValidInitialScheduler(); + } + STORM_LOG_THROW(requirements.empty(), storm::exceptions::UncheckedRequirementException, "Could not establish requirements of solver."); + } + if (initialScheduler) { + solver->setInitialScheduler(initialScheduler.get()); + } + solver->setRequirementsChecked(); + + storm::dd::Add result = solver->solveEquations(dir, model.getManager().template getAddZero(), subvector); return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), result))); } else { diff --git a/src/storm/models/sparse/Model.cpp b/src/storm/models/sparse/Model.cpp index dfda0fd97..99ae62213 100644 --- a/src/storm/models/sparse/Model.cpp +++ b/src/storm/models/sparse/Model.cpp @@ -330,12 +330,16 @@ namespace storm { for (uint_fast64_t state = 0, highestStateIndex = this->getNumberOfStates() - 1; state <= highestStateIndex; ++state) { if (subsystem == nullptr || subsystem->get(state)) { outStream << "\t" << state; - if (includeLabeling || firstValue != nullptr || secondValue != nullptr || stateColoring != nullptr) { + if (includeLabeling || firstValue != nullptr || secondValue != nullptr || stateColoring != nullptr || hasStateValuations()) { outStream << " [ "; // If we need to print some extra information, do so now. - if (includeLabeling || firstValue != nullptr || secondValue != nullptr) { - outStream << "label = \"" << state << ": "; + if (includeLabeling || firstValue != nullptr || secondValue != nullptr || hasStateValuations()) { + outStream << "label = \"" << state; + if (hasStateValuations()) { + outStream << " " << getStateValuations().getStateInfo(state); + } + outStream << ": "; // Now print the state labeling to the stream if requested. if (includeLabeling) { diff --git a/src/storm/models/sparse/StandardRewardModel.cpp b/src/storm/models/sparse/StandardRewardModel.cpp index 4385c46e1..ccf9b5d71 100644 --- a/src/storm/models/sparse/StandardRewardModel.cpp +++ b/src/storm/models/sparse/StandardRewardModel.cpp @@ -179,12 +179,12 @@ namespace storm { STORM_LOG_THROW(transitionMatrix.getRowGroupCount() == this->getStateActionRewardVector().size(), storm::exceptions::InvalidOperationException, "The reduction to state rewards is only possible if the size of the action reward vector equals the number of states."); if (weights) { if (this->hasStateRewards()) { - storm::utility::vector::applyPointwise(this->getStateActionRewardVector(), *weights, this->getStateRewardVector(), + storm::utility::vector::applyPointwiseTernary(this->getStateActionRewardVector(), *weights, this->getStateRewardVector(), [] (ValueType const& sar, MatrixValueType const& w, ValueType const& sr) -> ValueType { return sr + w * sar; }); } else { this->optionalStateRewardVector = std::move(this->optionalStateActionRewardVector); - storm::utility::vector::applyPointwise(this->optionalStateRewardVector.get(), *weights, this->optionalStateRewardVector.get(), [] (ValueType const& r, MatrixValueType const& w) { return w * r; } ); + storm::utility::vector::applyPointwise>(this->optionalStateRewardVector.get(), *weights, this->optionalStateRewardVector.get()); } } else { if (this->hasStateRewards()) { @@ -216,11 +216,11 @@ namespace storm { std::vector result; if (this->hasTransitionRewards()) { result = transitionMatrix.getPointwiseProductRowSumVector(this->getTransitionRewardMatrix()); - storm::utility::vector::applyPointwise(weights, this->getStateActionRewardVector(), result, [] (MatrixValueType const& weight, ValueType const& rewardElement, ValueType const& resultElement) { return weight * (resultElement + rewardElement); } ); + storm::utility::vector::applyPointwiseTernary(weights, this->getStateActionRewardVector(), result, [] (MatrixValueType const& weight, ValueType const& rewardElement, ValueType const& resultElement) { return weight * (resultElement + rewardElement); } ); } else { result = std::vector(transitionMatrix.getRowCount()); if (this->hasStateActionRewards()) { - storm::utility::vector::applyPointwise(weights, this->getStateActionRewardVector(), result, [] (MatrixValueType const& weight, ValueType const& rewardElement, ValueType const& resultElement) { return weight * rewardElement; } ); + storm::utility::vector::applyPointwise(weights, this->getStateActionRewardVector(), result, [] (MatrixValueType const& weight, ValueType const& rewardElement) { return weight * rewardElement; } ); } } if (this->hasStateRewards()) { diff --git a/src/storm/parser/PrismParser.cpp b/src/storm/parser/PrismParser.cpp index 0230fbaca..38ed0cb12 100644 --- a/src/storm/parser/PrismParser.cpp +++ b/src/storm/parser/PrismParser.cpp @@ -216,19 +216,19 @@ namespace storm { moduleDefinitionList %= +(moduleRenaming(qi::_r1) | moduleDefinition(qi::_r1))[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::modules, qi::_r1), qi::_1)]; moduleDefinitionList.name("module list"); - start = (qi::eps[phoenix::bind(&PrismParser::removeInitialConstruct, phoenix::ref(*this), qi::_a)] - > *(modelTypeDefinition[phoenix::bind(&PrismParser::setModelType, phoenix::ref(*this), qi::_a, qi::_1)] - | definedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_a), qi::_1)] - | undefinedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, qi::_a), qi::_1)] - | formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, qi::_a), qi::_1)] - | globalVariableDefinition(qi::_a) - | (moduleRenaming(qi::_a) | moduleDefinition(qi::_a))[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::modules, qi::_a), qi::_1)] - | initialStatesConstruct(qi::_a) - | rewardModelDefinition(qi::_a)[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::rewardModels, qi::_a), qi::_1)] - | labelDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::labels, qi::_a), qi::_1)] - | formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, qi::_a), qi::_1)] + start = (qi::eps[phoenix::bind(&PrismParser::removeInitialConstruct, phoenix::ref(*this), phoenix::ref(globalProgramInformation))] + > *(modelTypeDefinition[phoenix::bind(&PrismParser::setModelType, phoenix::ref(*this), phoenix::ref(globalProgramInformation), qi::_1)] + | definedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, phoenix::ref(globalProgramInformation)), qi::_1)] + | undefinedConstantDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::constants, phoenix::ref(globalProgramInformation)), qi::_1)] + | formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, phoenix::ref(globalProgramInformation)), qi::_1)] + | globalVariableDefinition(phoenix::ref(globalProgramInformation)) + | (moduleRenaming(phoenix::ref(globalProgramInformation)) | moduleDefinition(phoenix::ref(globalProgramInformation)))[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::modules, phoenix::ref(globalProgramInformation)), qi::_1)] + | initialStatesConstruct(phoenix::ref(globalProgramInformation)) + | rewardModelDefinition(phoenix::ref(globalProgramInformation))[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::rewardModels, phoenix::ref(globalProgramInformation)), qi::_1)] + | labelDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::labels, phoenix::ref(globalProgramInformation)), qi::_1)] + | formulaDefinition[phoenix::push_back(phoenix::bind(&GlobalProgramInformation::formulas, phoenix::ref(globalProgramInformation)), qi::_1)] ) - > -(systemCompositionConstruct(qi::_a)) > qi::eoi)[qi::_val = phoenix::bind(&PrismParser::createProgram, phoenix::ref(*this), qi::_a)]; + > -(systemCompositionConstruct(phoenix::ref(globalProgramInformation))) > qi::eoi)[qi::_val = phoenix::bind(&PrismParser::createProgram, phoenix::ref(*this), phoenix::ref(globalProgramInformation))]; start.name("probabilistic program"); // Enable location tracking for important entities. @@ -267,6 +267,7 @@ namespace storm { this->secondRun = true; this->expressionParser->setIdentifierMapping(&this->identifiers_); + this->globalProgramInformation.moveToSecondRun(); } void PrismParser::allowDoubleLiterals(bool flag) { diff --git a/src/storm/parser/PrismParser.h b/src/storm/parser/PrismParser.h index f285c5cc9..129cd7b43 100644 --- a/src/storm/parser/PrismParser.h +++ b/src/storm/parser/PrismParser.h @@ -30,6 +30,25 @@ namespace storm { actionIndices.emplace("", 0); } + void moveToSecondRun() { + // Clear all data except the action to indices mapping. + modelType = storm::prism::Program::ModelType::UNDEFINED; + constants.clear(); + formulas.clear(); + globalBooleanVariables.clear(); + globalIntegerVariables.clear(); + moduleToIndexMap.clear(); + modules.clear(); + rewardModels.clear(); + labels.clear(); + hasInitialConstruct = false; + initialConstruct = storm::prism::InitialConstruct(); + systemCompositionConstruct = boost::none; + + currentCommandIndex = 0; + currentUpdateIndex = 0; + } + // Members for all essential information that needs to be collected. storm::prism::Program::ModelType modelType; std::vector constants; @@ -50,7 +69,7 @@ namespace storm { uint_fast64_t currentUpdateIndex; }; - class PrismParser : public qi::grammar, Skipper> { + class PrismParser : public qi::grammar { public: /*! * Parses the given file into the PRISM storage classes assuming it complies with the PRISM syntax. @@ -161,8 +180,11 @@ namespace storm { // A function used for annotating the entities with their position. phoenix::function annotate; + // An object gathering information about the program while parsing. + GlobalProgramInformation globalProgramInformation; + // The starting point of the grammar. - qi::rule, Skipper> start; + qi::rule start; // Rules for model type. qi::rule modelTypeDefinition; diff --git a/src/storm/settings/SettingsManager.cpp b/src/storm/settings/SettingsManager.cpp index e38c5daf2..b271ca581 100644 --- a/src/storm/settings/SettingsManager.cpp +++ b/src/storm/settings/SettingsManager.cpp @@ -61,7 +61,6 @@ namespace storm { 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. @@ -289,7 +288,6 @@ namespace storm { this->addOption(option); } } - } void SettingsManager::addOption(std::shared_ptr