[scram] 01/02: Imported Upstream version 0.11.5

Olzhas Rakhimov rakhimov-guest at moszumanska.debian.org
Mon Dec 12 11:03:26 UTC 2016


This is an automated email from the git hooks/post-receive script.

rakhimov-guest pushed a commit to branch master
in repository scram.

commit d2710fe97c2b27f108729d0728d73dc50c635786
Author: rakhimov <ol.rakhimov at gmail.com>
Date:   Mon Dec 12 02:57:46 2016 -0800

    Imported Upstream version 0.11.5
---
 .appveyor.yml                                      |    7 +-
 .codecov.yml                                       |    2 +-
 .gitmodules                                        |    3 +
 .landscape.yml                                     |    1 +
 .travis.yml                                        |    4 +-
 .travis/doxygen.conf                               |    2 +-
 .travis/install.sh                                 |   25 +-
 .travis/run_tests.sh                               |    6 +-
 .travis/script.sh                                  |   12 +-
 CMakeLists.txt                                     |   39 +-
 README.rst                                         |   38 +-
 cmake/FindJeMalloc.cmake                           |   47 +
 doc/bugs.rst                                       |    7 +-
 doc/citation.rst                                   |   22 +
 doc/coding_standards.rst                           |   32 +-
 doc/config_file.rst                                |    2 +-
 doc/design_description.rst                         |  140 +-
 .../{shorthand_input.txt => aralia_input.txt}      |    0
 doc/fault_tree_analysis.rst                        |    4 +-
 doc/fault_tree_generator.rst                       |    2 +-
 doc/fta_algorithms.rst                             |   11 +-
 doc/fta_preprocessing.rst                          |    2 +-
 doc/gui.rst                                        |    4 +-
 doc/input_file.rst                                 |   30 +-
 doc/installation.rst                               |    2 +-
 doc/opsa_support.rst                               |   45 +-
 doc/performance.rst                                |    8 +-
 doc/probability_analysis.rst                       |   12 +-
 doc/references.rst                                 |   24 +-
 doc/release/release_checklist.rst                  |   16 +-
 doc/release/v0.11.5.md                             |   36 +
 doc/report_layer.rst                               |   12 +-
 doc/{scram.man => scram.1}                         |    6 +-
 doc/todo.rst                                       |    5 +-
 doc/xml_comments.rst                               |    2 +-
 gui/CMakeLists.txt                                 |    7 +-
 gui/event.cpp                                      |   46 +-
 gui/event.h                                        |  103 +-
 gui/gate.h                                         |   19 +-
 input/EventTreeExample/event_tree.xml              |    2 +-
 install.py                                         |    2 +-
 scripts/fault_tree.py                              |   36 +-
 scripts/fault_tree_generator.py                    |   19 +-
 scripts/fuzz_tester.py                             |   72 +-
 scripts/nqueens.py                                 |   28 +-
 scripts/shorthand_to_xml.py                        |  527 --------
 scripts/{ => test}/test_fault_tree_generator.py    |   21 +-
 scripts/test_shorthand_to_xml.py                   |  427 -------
 share/config.rng                                   |  103 +-
 share/input.rng                                    |    2 +-
 share/open-psa/curves.bnf                          |   11 -
 share/open-psa/mcs.bnf                             |   18 -
 share/open-psa/mef.dtd                             |  461 -------
 share/open-psa/mef.rnc                             |  539 --------
 share/open-psa/mef.rng                             | 1341 --------------------
 share/open-psa/stat_measures.bnf                   |   26 -
 share/report_layer.rng                             |   82 +-
 src/CMakeLists.txt                                 |   48 +-
 src/bdd.cc                                         |    1 -
 src/bdd.h                                          |   70 +-
 src/boolean_graph.cc                               |    5 +-
 src/boolean_graph.h                                |  103 +-
 src/ccf_group.cc                                   |   12 +-
 src/ccf_group.h                                    |    2 +-
 src/cycle.h                                        |    4 +-
 src/event.h                                        |    5 +-
 src/expression.cc                                  |  479 +------
 src/expression.h                                   |  659 +---------
 src/expression/arithmetic.cc                       |  114 ++
 src/expression/arithmetic.h                        |  196 +++
 src/expression/constant.cc                         |   53 +
 src/expression/constant.h                          |   82 ++
 src/expression/exponential.cc                      |  136 ++
 src/expression/exponential.h                       |  157 +++
 .../random_deviate.cc}                             |  292 +----
 src/expression/random_deviate.h                    |  267 ++++
 src/ext.h                                          |   13 +-
 src/fault_tree.cc                                  |    3 -
 src/fault_tree.h                                   |    2 +-
 src/fault_tree_analysis.cc                         |    3 +
 src/fault_tree_analysis.h                          |    7 +-
 src/importance_analysis.cc                         |    1 +
 src/importance_analysis.h                          |   44 +-
 src/initializer.cc                                 |   11 +-
 src/initializer.h                                  |    4 +-
 src/logger.cc                                      |   21 +-
 src/logger.h                                       |   18 +-
 src/model.cc                                       |   45 +
 src/model.h                                        |   39 +-
 src/{logger.cc => parameter.cc}                    |   39 +-
 src/parameter.h                                    |   93 ++
 src/preprocessor.cc                                |   59 +
 src/preprocessor.h                                 |    2 +
 src/probability_analysis.cc                        |   40 +-
 src/probability_analysis.h                         |  106 +-
 src/random.h                                       |  140 +-
 src/reporter.cc                                    |   14 +-
 src/reporter.h                                     |   13 +-
 src/risk_analysis.cc                               |   31 +-
 src/risk_analysis.h                                |   80 +-
 src/scram.cc                                       |   30 +-
 src/settings.h                                     |    2 +
 src/uncertainty_analysis.cc                        |   15 +
 src/uncertainty_analysis.h                         |   50 +-
 tests/CMakeLists.txt                               |    2 +-
 tests/bench_bscu_tests.cc                          |    8 +-
 tests/bench_core_tests.cc                          |    4 +-
 tests/bench_small_tree_tests.cc                    |   11 +-
 tests/ccf_group_tests.cc                           |    1 +
 tests/expression_tests.cc                          |    4 +
 tests/input/empty_attribute.xml                    |    2 +-
 tests/input/fta/doubly_defined_parameter.xml       |    2 +-
 tests/input/fta/run_inputs.py                      |   96 +-
 tests/input/unsupported_feature.xml                |    2 +-
 tests/performance_tests.cc                         |    3 +-
 tests/risk_analysis_tests.cc                       |   99 +-
 tests/risk_analysis_tests.h                        |  134 +-
 tests/test_scram_call.py                           |    2 +-
 118 files changed, 2549 insertions(+), 5933 deletions(-)

diff --git a/.appveyor.yml b/.appveyor.yml
index 9182b76..865b8a2 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -12,6 +12,7 @@ install:
     - set PATH=C:\msys64\mingw64\bin;C:\msys64\usr\bin;%PATH%
     - pacman --noconfirm -Syu
     - pacman --noconfirm -Syu
+    - pacman --noconfirm -S mingw-w64-x86_64-jemalloc
     - pacman --noconfirm -S mingw-w64-x86_64-boost
     - pacman --noconfirm -S mingw-w64-x86_64-libxml++2.6
     - pacman --noconfirm -S mingw-w64-x86_64-qt5
@@ -19,15 +20,11 @@ install:
 before_build:
     - md install
     - md build
-    - cd build
 
 build_script:
-    - cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=..\install -DCMAKE_BUILD_TYPE=%CONFIGURATION% ..
-    - make -j 2
+    - python .\install.py --mingw64 --prefix=.\install --build-type=%CONFIGURATION% -j 2
 
 after_build:
-    - make install
-    - cd ..
     - set PATH=%PATH%;%CD%\install\bin
 
 test_script:
diff --git a/.codecov.yml b/.codecov.yml
index 8627f00..8546493 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -5,4 +5,4 @@ coverage:
     ignore:
         - tests/*
         - src/*
-        - scripts/test_*
+        - scripts/test/*
diff --git a/.gitmodules b/.gitmodules
index b616270..8933f82 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
 [submodule "tests/googletest"]
 	path = tests/googletest
 	url = https://github.com/rakhimov/googletest
+[submodule "scripts/translators"]
+	path = scripts/translators
+	url = https://github.com/rakhimov/translators
diff --git a/.landscape.yml b/.landscape.yml
index 890fa1b..a2a896c 100644
--- a/.landscape.yml
+++ b/.landscape.yml
@@ -10,6 +10,7 @@ mccabe:
     options: {max-complexity: 15}
 pylint:
     enable: [bad-continuation, fixme]
+    options: {max-nested-blocks: 3}
 python-targets:
     - 2
     - 3
diff --git a/.travis.yml b/.travis.yml
index f93444f..ae68800 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,7 +20,7 @@ env:
     global:
         - PATH=$PATH:`pwd`/install/bin
         # Intel Parallel Studio
-        - secure: "BM1aLsCy0NYk1TCCMeQH6H1O9B+NmZeO6QzRTjy1Xrs8wvoKsuBiazjxSZ6nVWP3F+JtjsOLzeFyELmCf4lobcw8bhzgLZ7ZFaDJl4DC31w+87RdQFYzMe5t53SfflkfBDYkbpbUrt1B7qPk5r0nYDG+QzO3T/XnvSN/0HvmEBQ="
+        - secure: "AY6adQXVk/3J43z6PHbqVxq3Bn5HZ5Qrf8fvPeF+BR56Oa4+9YryfDDJyiDRISuyh7PoDUw+PERJiZpAL3rkFefxUkYTB3hdU4lsMIAgl37MuT4/kP5CW9TC+gsPJl41y4i8XKFtJXF1K4PW2oDRZCbDDB9oUWPZjNPPe0jg4e8="
     matrix:
         - RELEASE=
         - RELEASE=true
@@ -29,6 +29,8 @@ matrix:
     exclude:
         - os: osx
           compiler: gcc  # GCC is Clang on OS X.
+        - os: osx
+          env: RELEASE=  # OS X builds are slow and limited.
     include:
         - os: linux
           compiler: icc
diff --git a/.travis/doxygen.conf b/.travis/doxygen.conf
index b387651..5f8d038 100644
--- a/.travis/doxygen.conf
+++ b/.travis/doxygen.conf
@@ -769,7 +769,7 @@ FILE_PATTERNS          = *.h *.cc *.cc.in
 # be searched for input files as well.
 # The default value is: NO.
 
-RECURSIVE              = NO
+RECURSIVE              = YES
 
 # The EXCLUDE tag can be used to specify files and/or directories that should be
 # excluded from the INPUT source files. This way you can easily exclude a
diff --git a/.travis/install.sh b/.travis/install.sh
index 2ff27d8..ba287b5 100755
--- a/.travis/install.sh
+++ b/.travis/install.sh
@@ -11,8 +11,8 @@ if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
   brew install ccache
 fi
 
-sudo pip install -U pip wheel
-sudo pip install -r requirements-tests.txt
+sudo -H pip install -U pip wheel
+sudo -H pip install nose  # Testing main() requires nosetests!
 
 [[ "${TRAVIS_OS_NAME}" == "linux" ]] || exit 0
 
@@ -26,10 +26,10 @@ PROJECT_DIR=$PWD
 cd /tmp
 
 # Boost
-wget https://sourceforge.net/projects/iscram/files/deps/boost-scram.tar.bzip2
-tar -xf ./boost-scram.tar.bzip2  # Sets up install dir.
-sudo mv ./install/lib/* /usr/lib/
-sudo mv ./install/include/boost /usr/include/
+wget https://sourceforge.net/projects/iscram/files/deps/boost-scram.tar.gz
+tar -xf ./boost-scram.tar.gz
+sudo mv ./boost-scram/lib/* /usr/lib/
+sudo mv ./boost-scram/include/* /usr/include/
 
 # Libxml++
 LIBXMLPP='libxml++-2.38.1'
@@ -40,9 +40,18 @@ tar -xf ${LIBXMLPP}.tar.xz
 cd $PROJECT_DIR
 
 [[ -z "${RELEASE}" && "$CXX" = "g++" ]] || exit 0
+
+# Install newer doxygen due to bugs in 1.8.6 with C++11 code.
+DOXYGEN='doxygen-1.8.12.linux.bin.tar.gz'
+wget https://sourceforge.net/projects/iscram/files/deps/${DOXYGEN}
+tar -xf ${DOXYGEN}
+sudo cp doxygen-1.8.12/bin/* /usr/bin/
+
 sudo apt-get install -qq ggcov
 sudo apt-get install -qq valgrind
-sudo apt-get install -qq doxygen
-sudo pip install -r requirements-dev.txt
 sudo apt-get install -qq lcov
+
 gem install coveralls-lcov
+
+sudo -H pip install -r requirements-dev.txt
+sudo -H pip install -r requirements-tests.txt
diff --git a/.travis/run_tests.sh b/.travis/run_tests.sh
index 360e8c3..46a9827 100755
--- a/.travis/run_tests.sh
+++ b/.travis/run_tests.sh
@@ -7,13 +7,11 @@ set -ev
 which scram
 which scram_tests
 
-scram_tests --gtest_filter=-*Performance*
+scram_tests
 nosetests -w ./tests/
 
 if [[ -z "${RELEASE}" && "$CXX" = "g++" ]]; then
-  nosetests --with-coverage -w ./scripts/
-else
-  nosetests -w ./scripts/
+  nosetests --with-coverage -w scripts test/
 fi
 
 ./scripts/fault_tree_generator.py -b 200 -a 5
diff --git a/.travis/script.sh b/.travis/script.sh
index d66b761..b1629ce 100755
--- a/.travis/script.sh
+++ b/.travis/script.sh
@@ -43,11 +43,8 @@ valgrind --tool=memcheck --leak-check=full --show-leak-kinds=definite \
   || [[ $? -ne 127 ]]
 
 # Check documentation coverage
+which doxygen || exit 1
 doxygen ./.travis/doxygen.conf > /dev/null 2> doc_errors.txt
-# Deletion of compiler generated default functions
-sed -i '/=delete/d' doc_errors.txt
-# Doxygen 1.8.6 can't deal with C++11 initializer list in constructor.
-sed -i '/expression\.cc/d' doc_errors.txt
 if [[ -s doc_errors.txt ]]; then
   echo "Documentation errors:" >&2
   cat doc_errors.txt >&2
@@ -60,8 +57,11 @@ lizard -w -L 60 -a 5 -EIgnoreAssert -ENS -Ecpre src gui \
 lizard -w -L 60 -a 5 scripts/*.py
 
 # C++ linting
-cpplint --repository=../ --quiet src/* tests/* 2> style.txt \
+cpplint --repository=../ --quiet --recursive src/* 2> style.txt \
   || echo "TODO: Fix the C++ code"
+cpplint --repository=../ --quiet --filter=-build/include_what_you_use \
+  tests/* 2>> style.txt || echo "TODO: Fix the C++ code"
+
 # Clean false positives and noise
 sed -i '/Found C system header after C\+\+/d' style.txt
 sed -i '/Found C system header after other header/d' style.txt
@@ -77,4 +77,4 @@ if [[ -s style.txt ]]; then
 fi
 
 # Python linting
-prospector -P .landscape ./*.py scripts/*.py
+prospector ./*.py scripts/*.py
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8ae6226..fb3214d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,16 +14,19 @@ endif()
 project(SCRAM)
 set(SCRAM_VERSION_MAJOR 0)  # Indicate major API change after 1.0.0
 set(SCRAM_VERSION_MINOR 11)  # New features and improvements.
-set(SCRAM_VERSION_MICRO 4)  # Bug fixes.
+set(SCRAM_VERSION_MICRO 5)  # Bug fixes.
 
 ####################### Begin Options ###################
 
-set(BUILD_SHARED_LIBS TRUE)  # Change this for static building.
+option(BUILD_SHARED_LIBS OFF)
+
+option(INSTALL_LIBS "Install the generated libraries" ON)
 
 # Linking of external libraries, such as BOOST.
 option(WITH_STATIC_LIBS "Try to link against static libraries" OFF)
 
-option(WITH_TCMALLOC "Use TCMalloc" ON)
+option(WITH_TCMALLOC "Use TCMalloc if available (#1 preference)" ON)
+option(WITH_JEMALLOC "Use JEMalloc if available (#2 preference)" ON)
 
 option(WITH_COVERAGE "Instrument for coverage analysis" OFF)
 option(WITH_PROFILE "Instrument for performance profiling" OFF)
@@ -43,7 +46,7 @@ CHECK_CXX_COMPILER_FLAG("-std=c++1y" COMPILER_SUPPORTS_CXX14)
 if(NOT COMPILER_SUPPORTS_CXX14)
   message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support.")
 endif()
-add_definitions("-std=c++1y")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")
 
 set(CMAKE_CXX_FLAGS_DEBUG
   "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Werror -Wno-sign-compare -Wnon-virtual-dtor -Wno-missing-field-initializers")
@@ -66,8 +69,6 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR
 elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
   # TODO: Bug in Intel compiler with multi-initialization with auto.
   set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -diag-disable=3373")
-  # TODO: Bug in Intel compiler w/o GCC 5 built-in math with overlflow.
-  add_definitions(-D_GLIB_TEST_OVERFLOW_FALLBACK)  # TODO: Remove after glib2 version 2.48
 endif()
 
 if(WIN32)
@@ -76,6 +77,7 @@ endif()
 
 find_program(CCACHE_FOUND ccache)
 if(CCACHE_FOUND)
+  message(STATUS "Using CCache for builds")
   set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
   set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
 
@@ -118,7 +120,9 @@ set(CMAKE_SKIP_BUILD_RPATH FALSE)
 # (but later on when installing).
 set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
 
-set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
+if(INSTALL_LIBS)
+  set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
+endif()
 
 # Add the automatically determined parts of the RPATH,
 # which point to directories outside the build tree
@@ -132,13 +136,20 @@ list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
 
 ######################## Begin find libraries ######################
 
-set(LIBS "")
-
-# Optional TCMalloc for optimization.
-if(WITH_TCMALLOC AND NOT WITH_PROFILE)
+set(MALLOC "System Malloc")
+# Optional alternative Malloc for optimization.
+if(NOT WITH_PROFILE)
   find_package(Tcmalloc)
-  set(LIBS ${LIBS} ${Tcmalloc_LIBRARIES})
+  find_package(JeMalloc)
+  if(WITH_TCMALLOC AND Tcmalloc_FOUND)
+    set(LIBS ${LIBS} ${Tcmalloc_LIBRARIES})
+    set(MALLOC "TCMalloc")
+  elseif(WITH_JEMALLOC AND JEMALLOC_FOUND)
+    set(LIBS ${LIBS} ${JEMALLOC_LIBRARIES})
+    set(MALLOC "JEMalloc")
+  endif()
 endif()
+message(STATUS "The memory allocator: ${MALLOC}")
 
 # Find LibXML++ and dependencies.
 set(LIBXML++_MIN_VERSION "2.38.1")  # TODO: Fix the minimum version check.
@@ -161,7 +172,7 @@ endif()
 unset(Boost_INCLUDE_DIR CACHE)
 unset(Boost_LIBRARY_DIRS CACHE)
 find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS
-  program_options filesystem system date_time
+  program_options filesystem system date_time random
   REQUIRED)
 
 if(Boost_USE_STATIC_LIBS)
@@ -209,6 +220,8 @@ include_directories(SYSTEM "${LibXML++_INCLUDE_DIR}")
 include_directories(SYSTEM "${LibXML++Config_INCLUDE_DIR}")
 include_directories(SYSTEM ${Glibmm_INCLUDE_DIRS})  # TODO: libxml++ dependency.
 
+include_directories("${PROJECT_SOURCE_DIR}")  # Include the core headers via "src".
+
 add_subdirectory("${SCRAM_SOURCE_DIR}")
 add_subdirectory("${SCRAM_SHARE_DIR}")
 add_subdirectory("${SCRAM_INPUT_DIR}")
diff --git a/README.rst b/README.rst
index 2c4d149..9d4a49e 100644
--- a/README.rst
+++ b/README.rst
@@ -16,9 +16,9 @@ SCRAM
     :alt: Code Health
 .. image:: https://codecov.io/github/rakhimov/scram/coverage.svg?branch=develop
     :target: https://codecov.io/github/rakhimov/scram?branch=develop
-.. image:: https://badge.waffle.io/rakhimov/scram.svg?label=ready&title=Ready
+.. image:: https://badge.waffle.io/rakhimov/scram.svg?label=In%20Progress&title=in%20progress
     :target: https://waffle.io/rakhimov/scram
-    :alt: 'Stories in Ready'
+    :alt: 'Stories in Progress'
 
 |
 
@@ -31,8 +31,8 @@ probability calculations with importance analysis,
 and uncertainty analysis with Monte Carlo simulations.
 This tool can handle non-coherent fault trees, containing NOT logic.
 
-SCRAM input and report files are based on OpenPSA_ Model Exchange Format.
-For the current status of the OpenPSA MEF features in SCRAM,
+SCRAM input and report files are based on the Open-PSA_ `Model Exchange Format`_.
+For the current status of the Open-PSA MEF features in SCRAM,
 please see the `MEF Support`_ documentation.
 
 A complementary GUI front-end is under development
@@ -46,7 +46,8 @@ The documentation_ contains a full description of SCRAM,
 its current capabilities, and future additions.
 The latest stable release is packaged for `quick installation`_ on various platforms.
 
-.. _OpenPSA: http://open-psa.org
+.. _Open-PSA: http://open-psa.org
+.. _Model Exchange Format: http://open-psa.github.io/mef
 .. _MEF Support: http://scram-pra.org/doc/opsa_support.html
 .. _documentation: http://scram-pra.org
 .. _quick installation: http://scram-pra.org/doc/installation.html
@@ -80,6 +81,7 @@ Optional Dependencies
 Package                Minimum Version
 ====================   ==================
 `TCMalloc`             1.7
+`JEMalloc`             3.6
 ====================   ==================
 
 
@@ -91,7 +93,7 @@ Package                Minimum Version
 ====================   ==================
 `GCC/G++`              4.9
 `Clang/LLVM`           3.4
-`Intel`                17.0
+`Intel`                17.0.1
 ====================   ==================
 
 
@@ -105,7 +107,7 @@ or the following commands must be executed after a normal clone.
 
 .. code-block:: bash
 
-    git submodule init --update --recursive
+    git submodule update --init --recursive
 
 
 Installing Dependencies (Linux and Unix)
@@ -244,8 +246,7 @@ Various other flags are described by the script's help prompt.
 
     .../scram$ python install.py --help
 
-Other tools,
-such as the **fault tree generator** and **shorthand-to-XML** converter,
+Other tools, such as the **fault tree generator**,
 can be found in the ``scripts`` directory.
 These tools do not need compilation or installation.
 
@@ -273,6 +274,10 @@ Where ``package`` is replaced by the correct package name:
 #. libxml++2.6
 #. qt5
 
+and (optionally):
+
+#. jemalloc
+
 If Python has not already been installed on the system,
 Python installation takes the form of:
 
@@ -285,14 +290,14 @@ the following line will install all major dependencies:
 
 .. code-block:: bash
 
-    pacman --noconfirm -S python mingw-w64-x86_64-{gcc,make,cmake,boost,libxml++2.6,qt5}
+    pacman --noconfirm -S python mingw-w64-x86_64-{gcc,make,cmake,boost,libxml++2.6,qt5,jemalloc}
 
 The building and installation can be done with the ``install.py`` script
 in the root directory.
 
 .. code-block:: bash
 
-    .../scram$ python install.py --prefix=path/to/installation/directory -release --mingw64
+    .../scram$ python install.py --prefix=path/to/installation/directory --release --mingw64
 
 After installation,
 SCRAM must be run inside of the MSYS2 shell.
@@ -330,7 +335,7 @@ On command line, run help to get more detailed information:
     scram --help
 
 Various other useful tools and helper scripts,
-such as the **fault tree generator** and **shorthand-to-XML** converter,
+such as the **fault tree generator**,
 can be found in the ``scripts`` directory.
 Help prompts and the documentation have more details how to use these tools.
 
@@ -348,7 +353,7 @@ To test the tools in the ``scripts`` directory:
 
 .. code-block:: bash
 
-    nosetests -w scripts/
+    nosetests -w scripts/ test/
 
 To test the command-line call of SCRAM:
 
@@ -381,14 +386,16 @@ It is recommended to build SCRAM
 with assertions preserved
 and sanitizers enabled, for example,
 address sanitizer in GCC and Clang ``-fsanitize=address``.
+
 In order to speed up the fuzz testing,
 SCRAM may be built with optimizations but ``NDEBUG`` undefined.
+Additionally, multiple SCRAM instances can be run at once.
 
-An example command to run SCRAM 1000 times with auto-generated inputs and configurations:
+An example command to run SCRAM 1000 times with 4 parallel instances:
 
 .. code-block:: bash
 
-    fuzz_tester.py -n 1000
+    fuzz_tester.py -n 1000 -j 4
 
 The fuzz tester can be guided with options listed in its help prompt.
 Some options can be combined,
@@ -401,6 +408,7 @@ however, information messages are given to indicate the interpretation.
 
     fuzz_tester.py --help
 
+Fuzzing inputs and configurations are auto-generated.
 The fuzz tester collects run configurations, failures, and logs.
 The auto-generated inputs are preserved for failed runs.
 
diff --git a/cmake/FindJeMalloc.cmake b/cmake/FindJeMalloc.cmake
new file mode 100644
index 0000000..f36cbc6
--- /dev/null
+++ b/cmake/FindJeMalloc.cmake
@@ -0,0 +1,47 @@
+# - Try to find jemalloc
+# Once done this will define
+#  JEMALLOC_FOUND - System has jemalloc
+#  JEMALLOC_INCLUDE_DIRS - The jemalloc include directories
+#  JEMALLOC_LIBRARIES - The libraries needed to use jemalloc
+
+if(NOT JEMALLOC_USE_BUNDLED)
+  find_package(PkgConfig)
+  if (PKG_CONFIG_FOUND)
+    pkg_check_modules(PC_JEMALLOC QUIET jemalloc)
+  endif()
+else()
+  set(PC_JEMALLOC_INCLUDEDIR)
+  set(PC_JEMALLOC_INCLUDE_DIRS)
+  set(PC_JEMALLOC_LIBDIR)
+  set(PC_JEMALLOC_LIBRARY_DIRS)
+  set(LIMIT_SEARCH NO_DEFAULT_PATH)
+endif()
+
+set(JEMALLOC_DEFINITIONS ${PC_JEMALLOC_CFLAGS_OTHER})
+
+find_path(JEMALLOC_INCLUDE_DIR jemalloc/jemalloc.h
+          PATHS ${PC_JEMALLOC_INCLUDEDIR} ${PC_JEMALLOC_INCLUDE_DIRS}
+          ${LIMIT_SEARCH})
+
+# If we're asked to use static linkage, add libjemalloc.a as a preferred library name.
+if(JEMALLOC_USE_STATIC)
+  list(APPEND JEMALLOC_NAMES
+    "${CMAKE_STATIC_LIBRARY_PREFIX}jemalloc${CMAKE_STATIC_LIBRARY_SUFFIX}")
+endif()
+
+list(APPEND JEMALLOC_NAMES jemalloc)
+
+find_library(JEMALLOC_LIBRARY NAMES ${JEMALLOC_NAMES}
+  HINTS ${PC_JEMALLOC_LIBDIR} ${PC_JEMALLOC_LIBRARY_DIRS}
+  ${LIMIT_SEARCH})
+
+set(JEMALLOC_LIBRARIES ${JEMALLOC_LIBRARY})
+set(JEMALLOC_INCLUDE_DIRS ${JEMALLOC_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set JEMALLOC_FOUND to TRUE
+# if all listed variables are TRUE
+find_package_handle_standard_args(JeMalloc DEFAULT_MSG
+  JEMALLOC_LIBRARY JEMALLOC_INCLUDE_DIR)
+
+mark_as_advanced(JEMALLOC_INCLUDE_DIR JEMALLOC_LIBRARY)
diff --git a/doc/bugs.rst b/doc/bugs.rst
index aac9dca..1e42dff 100644
--- a/doc/bugs.rst
+++ b/doc/bugs.rst
@@ -13,6 +13,11 @@ Technical Issues
           low-level technical issues.
 
 - Copying Settings around is expensive (~100B)
-- mef::Gate and mef::Formula have ``type`` field instead of ``operator`` (reserved in C++)
+- core::Gate and mef::Formula have ``type`` field instead of ``operator`` (reserved in C++)
 - Static variables of class type with dynamic initialization.
 - Performance profile across platforms is not stable.
+- Builds are very demanding for the project size:
+  500 MiB/job memory and 3 min total time.
+  The major contributing factors may be
+  the template-heavy code
+  and coupled physical layout of the project components.
diff --git a/doc/citation.rst b/doc/citation.rst
new file mode 100644
index 0000000..9d499c9
--- /dev/null
+++ b/doc/citation.rst
@@ -0,0 +1,22 @@
+########
+Citation
+########
+
+To cite SCRAM in publications
+=============================
+
+| Olzhas Rakhimov (|year|).
+| SCRAM version |release| documentation: Command-line Risk Analysis Multi-tool.
+| URL http://scram-pra.org/
+
+|
+
+A BibTex entry for LaTeX users
+==============================
+
+| @book{,
+|   author = {Olzhas Rakhimov},
+|   title  = {{SCRAM} version |release| documentation: Command-line Risk Analysis Multi-tool},
+|   year   = {|year|},
+|   url    = {http://scram-pra.org/},
+| }
diff --git a/doc/coding_standards.rst b/doc/coding_standards.rst
index 82fab3e..5340661 100644
--- a/doc/coding_standards.rst
+++ b/doc/coding_standards.rst
@@ -114,8 +114,8 @@ Additional Coding Conventions
     .. code-block:: cpp
 
         double checked_div(double x, double y) {
-            if (!y) throw domain_error("");  // Bad. Looks like 'if (no y) then fail'.
-                                             // More explicit (y == 0) is better.
+            if (!y)                      // Bad. Looks like 'if (no y) then fail'.
+                throw domain_error("");  // More explicit (y == 0) is better.
             return x / y;
         }
 
@@ -184,13 +184,13 @@ Core C++ Code
       abbreviate it to ``p_``.
       Its getter/setter functions should have
       corresponding names, i.e., ``p()`` and ``p(double value)``.
-      Append extra description after ``p_``, e.g., ``p_total_``.
+      Append extra description after ``p_``, e.g., ``p_total_`` (a la Semantic Hungarian).
       Avoid abbreviating the name to ``prob``
       or fully spelling it to ``probability``.
 
     * For non-member probability variables:
 
-        + Prefer prefixing with ``p_``
+        + Prefer prefixing with ``p_`` (a la Semantic Hungarian)
           if the name has more description to the probability value, e.g., ``p_not_event``.
         + Prefer ``prob`` abbreviation
           for single word names indicating general probability values.
@@ -208,12 +208,12 @@ Core C++ Code
       This gate in fault tree analysis has many names
       (Voting, Combination, atleast, K/N),
       and there doesn't seem to be a consensus among sources and tools.
-      The OpenPSA MEF "atleast" best captures the nature of the gate;
+      The Open-PSA MEF "atleast" best captures the nature of the gate;
       however, the "atleast" is awkward to use in code and API
       (Atleast vs. AtLeast vs. atleast vs. at_least).
       In SCRAM, the "vote" word must be used consistently
       to represent this gate in code and API.
-      The code that deals with the OpenPSA MEF may use the "atleast".
+      The code that deals with the Open-PSA MEF may use the "atleast".
 
 - In performance-critical **analysis code**
   (BDD variable ordering, Boolean formula rewriting/preprocessing, etc.),
@@ -271,6 +271,7 @@ C++
 #. Google style conformance check with Cpplint_
 #. Common C++ code problem check with cppclean_
 #. Consistent code formatting with ClangFormat_
+#. Component dependency analysis with cppdep_
 
 .. _Gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
 .. _Coveralls: https://coveralls.io/github/rakhimov/scram
@@ -278,9 +279,10 @@ C++
 .. _Coverity: https://scan.coverity.com/projects/2555
 .. _CppCheck: https://github.com/danmar/cppcheck/
 .. _Lizard: https://github.com/terryyin/lizard
-.. _Cpplint: https://github.com/theandrewdavis/cpplint
+.. _Cpplint: https://github.com/cpplint/cpplint
 .. _cppclean: https://github.com/myint/cppclean
 .. _ClangFormat: http://clang.llvm.org/docs/ClangFormat.html
+.. _cppdep: https://pypi.python.org/pypi/cppdep
 
 
 Python
@@ -291,10 +293,10 @@ Python
 #. Code coverage check with coverage_ and reporting with Codecov_
 #. Continuous code quality control on Landscape_ with Prospector_
 
-.. _Pylint: http://www.pylint.org/
+.. _Pylint: https://www.pylint.org/
 .. _PyVmMonitor: http://www.pyvmmonitor.com/
-.. _coverage: http://nedbatchelder.com/code/coverage/
-.. _Codecov: https://codecov.io/github/rakhimov/scram?ref=develop
+.. _coverage: https://coverage.readthedocs.io/en/latest/
+.. _Codecov: https://codecov.io/github/rakhimov/scram
 .. _Landscape: https://landscape.io/
 .. _Prospector: https://github.com/landscapeio/prospector
 
@@ -339,7 +341,7 @@ with auto-generated analysis input files
 to discover bugs, bottlenecks, and assumption failures.
 
 .. _GoogleTest: https://github.com/google/googletest
-.. _Nose: https://nose.readthedocs.org/en/latest/
+.. _Nose: httpss://nose.readthedocs.io/en/latest/
 .. _Travis CI: https://travis-ci.org/rakhimov/scram
 .. _AppVeyor: https://ci.appveyor.com/project/rakhimov/scram
 
@@ -368,7 +370,7 @@ Version control and Versioning
 - `Atomic Commit`_
 - `Semantic Versioning`_
 
-.. _Git SCM: http://git-scm.com/
+.. _Git SCM: https://git-scm.com/
 .. _Branching Model: http://nvie.com/posts/a-successful-git-branching-model/
 .. _Writing Good Commit Messages: https://github.com/erlang/otp/wiki/Writing-good-commit-messages
 .. _On Commit Messages: http://who-t.blogspot.com/2009/12/on-commit-messages.html
@@ -417,8 +419,8 @@ Conventions in Documentation "Source Text"
 General
 -------
 
-- Prefer :ref:`shorthand_format` for the Boolean formula documentation.
-  This format uses the C-style bitwise logical operators for equations.
+- Prefer the :ref:`Aralia_format` for the Boolean formula documentation.
+  This format uses the C-style bit-wise logical operators for equations.
 
 
 reST Documentation Style
@@ -427,7 +429,7 @@ reST Documentation Style
 - Semantic Linefeeds
 - Two blank lines between sections with bodies
 - One blank line after a header before its body
-- Title ``#`` overlined and underlined
+- Part ``#`` overlined and underlined
 - Chapter ``*`` overlined and underlined
 - Section underlining and order ``=``, ``-``, ``~``, ``^``, ``+``
 - Point nesting and order ``-``, ``*``, ``+``
diff --git a/doc/config_file.rst b/doc/config_file.rst
index e5cef38..1530070 100644
--- a/doc/config_file.rst
+++ b/doc/config_file.rst
@@ -21,5 +21,5 @@ Validation Schemas
 Configuration File Example
 ==========================
 
-.. highlight:: xml
 .. literalinclude:: example/config.xml
+    :language: xml
diff --git a/doc/design_description.rst b/doc/design_description.rst
index dfb38f3..6721c14 100644
--- a/doc/design_description.rst
+++ b/doc/design_description.rst
@@ -7,69 +7,73 @@ Design Description
 
     Complex Dependency Diagram (TheDailyWTF)
 
-- XML Parser leverages external libraries to process XML files.
-
-- Validator validates XML configuration and input files against the RelaxNG schema.
-  The validation against the schema is an integral part of the initialization.
-  Values that pass the validation against the schema are not re-checked by users of those values.
-
-- Settings manages overall analysis settings per run.
-
-- Config manages program configurations and analysis settings from a configuration file.
-
-- Containers: models, fault trees, event trees, components.
-
-- Constructs: anything that is stored in containers and can be an input for analysis.
-  Note that some containers are constructs as well.
-
-- Initializer processes input files to construct a model
-  with fault trees, event trees, CCF, and other analysis containers and constructs.
-  This initialization phase validates the values and logic supplied from the input files.
-  The constructs and analyses are initialized according to the configurations
-  supplied from the configuration file and command-line.
-  After the initialization step,
-  it is not expected that constructs of the analysis change.
-
-- Risk Analyzer operates on the valid model
-  with the initialized fault, event trees, and other constructs
-  to provide the requested results.
-  It runs after the initialization phase with the user-specified analysis settings.
-
-- Analyzers of fault trees, event trees, CCF, uncertainty,
-  and other analysis kinds.
-  These analyzers are employed by the main Risk Analyzer
-  to produce final results.
-  Common facilities, utilities, and functionalities
-  can be shared among these analyzers.
-  Analyzers and analysis facilities are designed
-  in the spirit of `Design by Contract`_ and `Policy-based design`_
-  to keep the code simple and flexible with algorithms.
-
-    * Fault Tree Analyzer operates on one fault tree with a single top event,
-      and may provide primary events, intermediate events,
-      and  products (minimal cut sets or prime implicants) as output,
-      or other information about the passed fault tree.
-      This fault tree analyzer uses many other helper facilities
-      specifically designed to make the analysis efficient and fast.
-
-    * Probability Calculator accepts the results of Fault Tree Analyzer
-      to calculate the total probability
-      and to provide facilities for other Quantitative analyzers.
-
-    * Importance Analyzer calculates
-      importance factors of *important* basic events
-      with Probability Calculator facilities.
-
-    * Uncertainty Analyzer uses Probability Calculator facilities
-      to sample basic event probabilities
-      and calculate the total probability.
-      Sampled results are processed to find statistical information,
-      such as mean, confidence ranges, standard deviation, and distributions.
-
-- Supporting classes: Formula, Expressions.
-
-- Reporter outputs the results of the work of Risk Analyzer
-  to specified files or streams in XML format.
+Core
+====
+
+#. XML Parser leverages external libraries to process XML files.
+
+#. Validator validates XML configuration and input files against the RelaxNG schema.
+   The validation against the schema is an integral part of the initialization.
+   Values that pass the validation against the schema are not re-checked by users of those values.
+
+#. Settings manages overall analysis settings per run.
+#. Config manages program configurations and analysis settings from a configuration file.
+#. Containers: models, fault trees, event trees, components.
+
+#. Analysis constructs: anything that is stored in containers and can be an input for analysis.
+   Note that some containers are constructs as well.
+
+    * Formula, Expressions, and other facilities used by the analysis constructs.
+
+#. Initializer processes input files to construct a model
+   with fault trees, event trees, CCF, and other analysis containers and constructs.
+   This initialization phase validates the values and logic supplied from the input files.
+   The constructs and analyses are initialized according to the configurations
+   supplied from the configuration file and command-line.
+   After the initialization step,
+   it is not expected that constructs of the analysis change.
+
+#. Risk Analyzer operates on a valid model
+   with initialized fault, event trees, and other constructs
+   to provide the requested results.
+   It runs after the initialization phase with the user-specified analysis settings.
+
+#. Analyzers of fault trees, event trees, CCF, uncertainty,
+   and other analysis kinds.
+   These analyzers are employed by the main Risk Analyzer
+   to produce final results.
+   Common facilities, utilities, and functionalities
+   can be shared among these analyzers.
+   Analyzers and analysis facilities are designed
+   in the spirit of `Design by Contract`_ and `Policy-based design`_
+   to keep the code simple and flexible with algorithms.
+
+    1. Fault Tree Analyzer operates on one fault tree with a single top event,
+       and may provide primary events, intermediate events,
+       and  products (minimal cut sets or prime implicants) as output,
+       or other information about the passed fault tree.
+       This fault tree analyzer uses many other helper facilities
+       specifically designed to make the analysis efficient and fast.
+
+    2. Probability Calculator accepts the results of Fault Tree Analyzer
+       to calculate the total probability
+       and to provide facilities for other Quantitative analyzers.
+
+    3. Importance Analyzer calculates
+       importance factors of *important* basic events
+       with Probability Calculator facilities.
+
+    4. Uncertainty Analyzer uses Probability Calculator facilities
+       to sample basic event probabilities
+       and calculate the total probability.
+       Sampled results are processed to find statistical information,
+       such as mean, confidence ranges, standard deviation, and distributions.
+
+#. Reporter outputs the results of the work of Risk Analyzer
+   to specified files or streams in XML format.
+
+#. Support components:
+   Logger, XML stream, and library extensions in the ext namespace.
 
 .. _Design by Contract: https://en.wikipedia.org/wiki/Design_by_contract
 .. _Policy-based design: https://en.wikipedia.org/wiki/Policy-based_design
@@ -78,6 +82,12 @@ Design Description
 API Documentation
 =================
 
-`API Docs Generated by Doxygen`_
+`API Docs Generated by Doxygen <../api/index.xhtml>`_
 
-.. _API Docs Generated by Doxygen: http://scram-pra.org/api/
+
+cppdep Component Dependency Report
+==================================
+
+.. image:: ../build/scram_core.svg
+
+.. literalinclude:: ../build/dep_report.txt
diff --git a/doc/example/shorthand_input.txt b/doc/example/aralia_input.txt
similarity index 100%
rename from doc/example/shorthand_input.txt
rename to doc/example/aralia_input.txt
diff --git a/doc/fault_tree_analysis.rst b/doc/fault_tree_analysis.rst
index cc2b68c..958ae63 100644
--- a/doc/fault_tree_analysis.rst
+++ b/doc/fault_tree_analysis.rst
@@ -47,10 +47,10 @@ Representation of INHIBIT, Undeveloped, and Conditional
 =======================================================
 
 These gate and event types are not directly supported
-by the input format based on the OpenPSA [MEF]_.
+by the input format based on the Open-PSA [MEF]_.
 Indeed, these types are treated just like AND gate and Basic event respectively;
 therefore, the description of these types
-can be given through the OpenPSA MEF "attribute" element for gates and events.
+can be given through the Open-PSA MEF "attribute" element for gates and events.
 The attribute name "flavor" is used to indicate
 the different representation of an event as shown in the description bellow.
 
diff --git a/doc/fault_tree_generator.rst b/doc/fault_tree_generator.rst
index 0d5d5d5..cf1b8d0 100644
--- a/doc/fault_tree_generator.rst
+++ b/doc/fault_tree_generator.rst
@@ -47,7 +47,7 @@ Script Arguments
   Complex gates (K/N, NOT, XOR) are created
   only if the weights are given.
 - Output file name.
-- Output formats: shorthand or XML(default).
+- Output formats: Aralia or XML(default).
 - An option to merge gates into nested formulas for the output.
 
 .. note::
diff --git a/doc/fta_algorithms.rst b/doc/fta_algorithms.rst
index 33aec21..dd3ce9f 100644
--- a/doc/fta_algorithms.rst
+++ b/doc/fta_algorithms.rst
@@ -76,8 +76,8 @@ complicates failure scenarios
 or may be irrelevant at all
 if the probability of success is close to 1.
 
-Minimal cut sets can be used for non-coherent analysis
-as conservative approximations.
+Minimal cut sets can be used as a conservative, approximate result
+for analysis of non-coherent fault trees.
 In order to eliminate complements of variables,
 it is assumed that a complement of an event always occurs, i.e., constant True or 1,
 unless the complement is in the same path or set as the corresponding event.
@@ -105,7 +105,7 @@ the event is repair (success) relevant.
 If an event is not in a product,
 it is irrelevant.
 
-Given Boolean formula **f(a,b,c)**:
+Given Boolean formula :math:`f(a,b,c)`:
 
     .. math::
 
@@ -118,13 +118,14 @@ Considering the complement is always True, the formula is simplified:
         f(a,b,c) = a \& b \| c
 
 Computation of prime implicants requires computation of the consensus
-when variable **a** is irrelevant:
+when variable :math:`a` is irrelevant:
 
     .. math::
 
         f(a,b,c) = a \& b \| \overline{a} \& c \| b \& c
 
-Minimal cut sets of the formula are ``{ab, c}``. Prime implicants are ``{ab, ~ac, bc}``.
+Minimal cut sets of the formula are :math:`{ab, c}`.
+Prime implicants are :math:`{ab, ~ac, bc}`.
 
 
 ********************
diff --git a/doc/fta_preprocessing.rst b/doc/fta_preprocessing.rst
index 45c9569..c86a1c6 100644
--- a/doc/fta_preprocessing.rst
+++ b/doc/fta_preprocessing.rst
@@ -171,7 +171,7 @@ and its failure logic to the failure destinations.
 The generalization of this technique
 comes from the observations
 of special cases for the Shannon decomposition.
-Given a Boolean formula **f(x, y)**,
+Given a Boolean formula :math:`f(x, y)`,
 the following cases are the special cases of its Shannon decomposition:
 
     1. If ``f(x, y) = 1/True/Failure`` assuming ``x = 1/True/Failure``:
diff --git a/doc/gui.rst b/doc/gui.rst
index 0ba6e89..8fba094 100644
--- a/doc/gui.rst
+++ b/doc/gui.rst
@@ -4,7 +4,7 @@ GUI Front-End
 
 The GUI front-end is developed with `Qt5 and Qt Creator`_.
 
-.. _Qt5 and Qt Creator: http://qt-project.org/
+.. _Qt5 and Qt Creator: https://www.qt.io/developers/
 
 
 GUI Concerns
@@ -104,4 +104,4 @@ Human Interface Guidelines
 - `XFCE HIG <https://wiki.xfce.org/dev/hig/general>`_
 - `The basic concepts of UI`_
 
-.. _The basic concepts of UI: http://www.usability.gov/what-and-why/user-interface-design.html
+.. _The basic concepts of UI: https://www.usability.gov/what-and-why/user-interface-design.html
diff --git a/doc/input_file.rst b/doc/input_file.rst
index 6cdfc8c..469953e 100644
--- a/doc/input_file.rst
+++ b/doc/input_file.rst
@@ -8,16 +8,16 @@ See :ref:`xml_tools` for more convenient writing and reading of XML input files.
 Currently, only fault trees are accepted for analysis,
 and one model per run is assumed.
 The input file format follows
-OpenPSA Model Exchange Format ([MEF]_) version 2.0d or later.
-The extensive description is given in the above format documentation by OpenPSA,
+the Open-PSA Model Exchange Format ([MEF]_) version 2.0d or later.
+The extensive description is given in the above format documentation by Open-PSA,
 and input files should be straightforward to create and understand.
-However, not all OpenPSA formatting is supported,
+However, not all Open-PSA formatting is supported,
 and some additional assumptions/restrictions are made by SCRAM.
 See :ref:`opsa_support` for the format description
 and current implementation with differences.
 
 In addition to the XML format,
-the :ref:`shorthand_format` is supported indirectly.
+the :ref:`Aralia_format` is supported indirectly.
 
 
 Encodings
@@ -38,7 +38,7 @@ Steps in XML Input Validation
     - The first file must define the name, label, and attributes of the model.
       Other files with this kind of information are ignored without a warning.
       This feature allows reuse of files from other models
-      without the need for the OpenPSA MEF ``include`` directives.
+      without the need for the Open-PSA MEF ``include`` directives.
 
 #. An XML input file is validated against the RelaxNG_ :ref:`schema`.
 #. The fault tree validation assumptions/requirements:
@@ -49,7 +49,7 @@ Steps in XML Input Validation
     - Public names must be unique globally,
       and private names must be unique locally within containers.
     - References are followed according to the public and private roles
-      described in the OpenPSA MEF section
+      described in the Open-PSA MEF section
       *IV.3.2. Solving Name Conflicts: Public versus Private Elements*.
 
 #. Additional validation of fault trees and values of parameters is performed:
@@ -109,18 +109,18 @@ Validation Schemas
 - `RelaxNG Schema <https://github.com/rakhimov/scram/blob/master/share/input.rng>`_
 
 
-.. _shorthand_format:
+.. _Aralia_format:
 
-Shorthand Input Format
-======================
+Aralia Input Format
+===================
 
 A more convenient format than the XML for writing simple fault trees
 utilizes a shorter notation for gates, operators (``&``, ``|``, ``@``, ``~``, ``^``), and events
 to create a collection of Boolean equations.
-The shorthand format can be converted into the XML format with `this script`_.
+The Aralia format can be converted into the XML format with `this script`_.
 
 .. _this script:
-    https://github.com/rakhimov/scram/blob/master/scripts/shorthand_to_xml.py
+    https://github.com/open-psa/translators/blob/master/aralia.py
 
 
 Input File Examples
@@ -129,13 +129,13 @@ Input File Examples
 Fault Tree Input File
 ---------------------
 
-.. highlight:: xml
 .. literalinclude:: example/input.xml
+    :language: xml
 
 
-Shorthand Version
------------------
+Aralia Version
+--------------
 
-.. literalinclude:: example/shorthand_input.txt
+.. literalinclude:: example/aralia_input.txt
 
 .. _RelaxNG: http://relaxng.org/
diff --git a/doc/installation.rst b/doc/installation.rst
index bd1c4a3..a093ca0 100644
--- a/doc/installation.rst
+++ b/doc/installation.rst
@@ -2,7 +2,7 @@
 Installation Instructions
 #########################
 
-.. note: Some SCRAM tools and tests may be absent in distribution packages.
+.. note:: Some SCRAM tools and tests may be absent in distribution packages.
 
 
 Ubuntu 14.04 or later
diff --git a/doc/opsa_support.rst b/doc/opsa_support.rst
index 397083c..34acc57 100644
--- a/doc/opsa_support.rst
+++ b/doc/opsa_support.rst
@@ -1,6 +1,6 @@
-#############################
-OpenPSA Model Exchange Format
-#############################
+##################################
+The Open-PSA Model Exchange Format
+##################################
 
 Open Probabilistic Safety Assessment Initiative hopes
 to bring international community of PSA together
@@ -22,7 +22,7 @@ The initiative deals with the following issues in the current PSA:
     - No universal format for industry data
 
 In order to facilitate information exchange and quality assurance,
-OpenPSA community has developed a model exchange format([MEF]_) for PSA
+The Open-PSA community has developed a model exchange format([MEF]_) for PSA
 that covers most needs to describe the analysis input for PSA tools.
 Moreover, the MEF defines the following requirements
 for its development and use:
@@ -41,22 +41,12 @@ This paradigm is followed from the structured programming techniques.
 More information about the initiative and format can be found on http://open-psa.org
 
 
-.. _opsa_mef_schema:
-
-OpenPSA MEF Schemas
-===================
-
-- `MEF RelaxNG Schema <https://github.com/rakhimov/scram/blob/master/share/open-psa/mef.rng>`_
-- `MEF RelaxNG Compact Schema <https://github.com/rakhimov/scram/blob/master/share/open-psa/mef.rnc>`_
-- `MEF DTD <https://github.com/rakhimov/scram/blob/master/share/open-psa/mef.dtd>`_
-
-
 .. _opsa_support:
 
-Currently Supported OpenPSA MEF Features
-========================================
+Currently Supported Open-PSA MEF Features
+=========================================
 
-The difference between :ref:`opsa_mef_schema` and :ref:`schema` can be used
+The difference between `the Open-PSA MEF schema`_ and SCRAM's :ref:`schema` can be used
 to identify the supported and unsupported features.
 
 - Label
@@ -88,13 +78,16 @@ to identify the supported and unsupported features.
     * Constant expressions
     * System mission time
     * Parameter
+    * Arithmetic expressions
     * Random deviate (normal, log-normal, histogram, uniform, gamma, beta)
     * Built-in expressions (exponential with two parameters,
       exponential with four parameters, Weibull)
 
+- `the Open-PSA MEF schema <https://github.com/open-psa/schemas/>`_
+
 
-Deviations from OpenPSA MEF
-===========================
+Deviations from the Open-PSA MEF
+================================
 
 - Names and references are case-sensitive
   and restricted to fewer characters and combinations.
@@ -108,17 +101,13 @@ Deviations from OpenPSA MEF
 - Common cause model levels for factors are required
   and must be strictly sequential in ascending order.
 - Attributes are not inherited.
-- The decimal separator for floating-point numbers is ``.`` (dot)
-  regardless of the locale.
-  The scientific notation for floating-point numbers is recognized
-  with ``e`` or ``E`` for the exponent.
 - An empty text in XML attributes or elements is considered an error.
 
 
-OpenPSA MEF Converters
-======================
+Translators to the Open-PSA MEF
+===============================
 
-- `Python script`_ for :ref:`shorthand_format` to OpenPSA MEF XML conversion.
+Various translators from other formats, such as Aralia,
+can be found in `the Open-PSA MEF translators repository`_.
 
-.. _Python script:
-    https://github.com/rakhimov/scram/blob/master/scripts/shorthand_to_xml.py
+.. _the Open-PSA MEF translators repository: https://github.com/open-psa/translators/
diff --git a/doc/performance.rst b/doc/performance.rst
index 2861edb..0c4cc60 100644
--- a/doc/performance.rst
+++ b/doc/performance.rst
@@ -33,7 +33,7 @@ System Specs     Version
 ==============   ===================
 Processor         Core i7-2820QM
 OS                Ubuntu 16.04 64bit
-GCC version       5.3.1
+GCC version       5.4.0
 Boost version     1.58
 Libxml2           2.9.3
 TCMalloc          2.4
@@ -166,14 +166,14 @@ Debug build:
 Release build:
 ~~~~~~~~~~~~~~
 
-- BDD Time: 1.6
+- BDD Time: 1.4
 - ZBDD Time: 0.20
 
 - # of BDD vertices created: 2652730
 - # of ITE in unique table: 2370567
 - # of ITE in BDD: 1123292 | 1160828
 
-- Memory:   250
+- Memory:   215
 
 - Cache-misses:  46 %  |  50 %
 
@@ -193,7 +193,7 @@ Release build:
 - ZBDD Cut set extraction memory: 100
 - Cut set indices to pointers memory: 90
 
-- Memory: 375
+- Memory: 310
 
 - Cache-misses:  34 %
 
diff --git a/doc/probability_analysis.rst b/doc/probability_analysis.rst
index e0f15cb..99fe2d5 100644
--- a/doc/probability_analysis.rst
+++ b/doc/probability_analysis.rst
@@ -9,32 +9,32 @@ Probability Types
 *****************
 
 Various probability types and distributions are accepted
-as described in the OpenPSA Model Exchange Format [MEF]_,
+as described in the Open-PSA Model Exchange Format [MEF]_,
 for example, constant values, exponential with two or four parameters,
 and uniform, normal, log-normal distributions.
 
 Bellow is a brief description.
 For more information, please take a look at the [MEF]_ format documentation.
 
-**P-model**
+P-model
     The probability of an event occurring
     when the time to failure is unknown or unpredictable.
 
-**Lambda-model or Exponential with Two Parameters**
-    The probability that a primary event will occur within given time (t).
+Lambda-model or Exponential with Two Parameters
+    The probability that a primary event will occur within given time (:math:`t`).
     Appropriate for events within systems
     that are continuously operating and
     have a known probability of failure during a unit time period (:math:`\lambda`).
 
     .. math::
 
-        P = 1-\exp(-\lambda*t)
+        P = 1-e^{-\lambda \cdot t}
 
     For small lambda and time, the approximation is
 
     .. math::
 
-        P \approx \lambda*t
+        P \approx \lambda \cdot t
 
 
 ************************
diff --git a/doc/references.rst b/doc/references.rst
index cebec4b..d1de146 100644
--- a/doc/references.rst
+++ b/doc/references.rst
@@ -17,13 +17,13 @@ Papers
 
 .. [DR96] Y. Dutuit and A. Rauzy,
           "A linear time algorithm to find modules of fault trees,"
-          IEEE Trans. Rel., vol. 45, no. 3, pp. 422-425, 1996.
+          IEEE Trans. Reliab. Eng. Syst. Saf., vol. 45, no. 3, pp. 422-425, 1996.
 
 .. [DR01] Y. Dutuit and A. Rauzy,
           "Efficient algorithms to assess component and gate importance in fault tree analysis,"
-          Reliab. Eng. Syst. Saf., vol. 72, no. 2, pp. 213-222, 2001.
+          IEEE Trans. Reliab. Eng. Syst. Saf., vol. 72, no. 2, pp. 213-222, 2001.
 
-.. [Jun09] W. Jung
+.. [Jun09] W. Jung,
            "ZBDD algorithm features for an efficient probabilistic safety assessment,"
            Nuc. Eng. Des., vol. 239, pp. 2085-2092, 2009.
 
@@ -33,27 +33,27 @@ Papers
 
 .. [Nie94] I. Niemelä,
            "On simplification of large fault trees,"
-           Reliab. Eng. Syst. Saf., vol. 44, pp. 135-138, 1994.
+           IEEE Trans. Reliab. Eng. Syst. Saf., vol. 44, pp. 135-138, 1994.
 
 .. [NR99] M. Nikolskaia and A. Rauzy,
           "Fine-tuning of boolean formulae preprocessing techniques,"
           in Proc. ESREL Conf., vol. 2, pp. 1027-1032, 1999.
 
-.. [PA09] R. Remenyte-Prescott and J. Andrews
+.. [PA09] R. Remenyte-Prescott and J. Andrews,
           "An efficient real-time method of analysis for non-coherent fault trees,"
           Qual. Reliab. Eng. Int., no. 25, pp. 129-150, 2009.
 
 .. [Rau93] A. Rauzy,
            "New algorithms for fault trees analysis,"
-           Reliab. Eng. Syst. Saf., vol. 5, no. 59, pp. 203-211, 1993.
+           IEEE Trans. Reliab. Eng. Syst. Saf., vol. 5, no. 59, pp. 203-211, 1993.
 
 .. [Rau01] A. Rauzy,
            "Mathematical foundation of minimal cutsets,"
-           IEEE Trans. Rel., vol. 50, no. 4, pp. 389-396, 2001
+           IEEE Trans. Reliab. Eng. Syst. Saf., vol. 50, no. 4, pp. 389-396, 2001
 
 .. [Rau03] A. Rauzy,
-           "Towards an efficient implementation of MOCUS," IEEE Trans.
-           Reliab. Eng. Syst. Saf., vol. 52, no. 2, pp. 175-180, 2003.
+           "Towards an efficient implementation of MOCUS,"
+           IEEE Trans. Reliab. Eng. Syst. Saf., vol. 52, no. 2, pp. 175-180, 2003.
 
 .. [WakXX] D. Wakefield,
            "You can't just build trees and call it PSA"
@@ -62,9 +62,9 @@ Papers
 Standards, Guides, Manuals, Handbooks
 =====================================
 
-.. [MEF] `OpenPSA Model Exchange Format <http://open-psa.org/joomla1.5/index.php?option=com_content&view=category&id=4&Itemid=19>`_
+.. [MEF] `Open PSA Model Exchange Format <https://open-psa.github.io/mef>`_
 
-.. [NUREG0492] `NRC NUREG-0492 <http://www.nrc.gov/reading-rm/doc-collections/nuregs/staff/sr0492/sr0492.pdf>`_
+.. [NUREG0492] `NRC NUREG-0492 <http://www.nrc.gov/reading-rm/doc-collections/nuregs/staff/sr0492/>`_
 
 .. [WASH1400] `NRC NUREG-75/014 (WASH-1400), Appendices III & IV <http://www.nrc.gov/reading-rm/doc-collections/nuregs/staff/sr75-014/appendix-iii-iv/>`_
 
@@ -80,7 +80,7 @@ Standards, Guides, Manuals, Handbooks
 Web Resources
 =============
 
-.. [OPSA] `OpenPSA Initiative <http://open-psa.org>`_
+.. [OPSA] `The Open-PSA Initiative <http://open-psa.org>`_
 
 .. [PRA] `PRA Wiki Page <https://en.wikipedia.org/wiki/Probabilistic_risk_assessment>`_
 .. [FTA] `FTA Wiki Page <https://en.wikipedia.org/wiki/Fault_tree_analysis>`_
diff --git a/doc/release/release_checklist.rst b/doc/release/release_checklist.rst
index b131d41..e1b6512 100644
--- a/doc/release/release_checklist.rst
+++ b/doc/release/release_checklist.rst
@@ -5,7 +5,7 @@ Release Checklist
 .. note::
     This checklist is for release actions.
     A copy of this file must be used for actual marking
-    without submitting it to version control system.
+    without submitting it to the version control system.
 
 .. note:: '[-]' is used to indicate currently failing or unachieveable step.
 
@@ -32,7 +32,7 @@ Pre-Release
 
     * [ ] Run all *fast* tests under Valgrind memcheck
 
-- [ ] Check compatibility with Python2 and Python3 (tools: Ninja-IDE)
+- [ ] Check compatibility with Python2 and Python3 (tools: pylint)
 - [ ] Update documentation (RST files)
 
     * [ ] Grammar check the documentation (optional)
@@ -61,20 +61,22 @@ Release
 
     * Commit the release with *SCRAM x.y.z* (x, y, z being version numbers)
 
+- [ ] Release with GitHub automatic tagging with the release notes
+
+    * [ ] Close the milestone on GitHub
+
+- [ ] Rebase Master on Develop (Avoid merging)
+
 - [ ] Update the website
 
-    * [ ] Version number in ``conf.py`` on the ``gh-source`` branch
     * [ ] Lizard CCN report
     * [ ] Sitemap
 
-- [ ] Release with GitHub automatic tagging with the release notes
-- [ ] Rebase Master on Develop (Avoid merging)
-- [ ] Close the milestone on GitHub
 - [ ] Publish the release notes on the scram-announce mailing list
 
 
 Distribution
 ============
 
-- [ ] Update PPA (DEB/Ubuntu)
+- [ ] Update Alioth/PPA (Debian/Ubuntu)
 - [ ] Installation package (NSIS/Windows)
diff --git a/doc/release/v0.11.5.md b/doc/release/v0.11.5.md
new file mode 100644
index 0000000..3e3d620
--- /dev/null
+++ b/doc/release/v0.11.5.md
@@ -0,0 +1,36 @@
+# Release Notes v0.11.5 : Debian Science Package
+
+This release includes patches from the initial Debian packaging
+at SCRAM's Alioth [repository](https://anonscm.debian.org/git/debian-science/packages/scram.git/).
+In addition, some changes have been inspired by
+the Open-PSA community workshop and its new [presence](https://github.com/open-psa/) at GitHub.
+
+
+## Minor Changes
+
+- Optional link against JEMalloc
+- Debian Science package
+- Parallelized fuzz testing
+- Move the Open-PSA schemas to https://github.com/open-psa/schemas
+- Move the ``shorthand_to_xml.py`` translator to https://github.com/open-psa/translators
+- Rename the shorthand format to the Aralia format
+- Improved build-times after dependency analysis and refactoring with
+  [cppdep](https://github.com/rakhimov/cppdep)
+- Python API documentation generation with Sphinx
+
+
+## Bug Fixes
+
+- CCF Alpha factor wrong formula (#146)
+- Misinterpretation of Log-Normal Deviate Error Factor and Level parameters (#147)
+
+
+## Since v0.11.4
+
+55 commits resulted in 123 files changed, 3114 insertions(+), 5925 deletions(-)
+
+- Core : 47 files changed, 1969 insertions(+), 1640 deletions(-)
+- Scripts : 9 files changed, 284 insertions(+), 1203 deletions(-)
+- GUI : 4 files changed, 112 insertions(+), 63 deletions(-)
+- Tests : 15 files changed, 177 insertions(+), 195 deletions(-)
+- Documentation : 25 files changed, 344 insertions(+), 279 deletions(-)
diff --git a/doc/report_layer.rst b/doc/report_layer.rst
index dcd9dcb..09a3e35 100644
--- a/doc/report_layer.rst
+++ b/doc/report_layer.rst
@@ -2,12 +2,12 @@
 Report Layer
 ############
 
-***********
-OpenPSA MEF
-***********
+****************
+The Open-PSA MEF
+****************
 
 The results of calculations are reported in the XML format
-suggested by OpenPSA Model Exchange Format ([MEF]_).
+suggested by the Open-PSA Model Exchange Format ([MEF]_).
 It is expected that the standardized report format be used by other tools
 to further analyze and operate on the results of PSA tools.
 The report contains two constructs:
@@ -59,7 +59,7 @@ The report contains two constructs:
 Encodings
 =========
 
-There is no specification for file encodings in OpenPSA MEF.
+There is no specification for file encodings in the Open-PSA MEF.
 SCRAM results are reported with the UTF-8 character set
 regardless of what the input file encodings are.
 
@@ -97,5 +97,5 @@ Suggested tools:
 Report File Example
 ===================
 
-.. highlight:: xml
 .. literalinclude:: example/report.xml
+    :language: xml
diff --git a/doc/scram.man b/doc/scram.1
similarity index 93%
rename from doc/scram.man
rename to doc/scram.1
index 3028f5e..ff90c31 100644
--- a/doc/scram.man
+++ b/doc/scram.1
@@ -1,4 +1,4 @@
-.TH SCRAM "1" "September 2016" "SCRAM 0.11.4" "SCRAM Manual"
+.TH SCRAM "1" "December 2016" "SCRAM 0.11.5" "SCRAM Manual"
 .SH NAME
 SCRAM \- Command-line Risk Analysis Multi-tool
 .SH SYNOPSIS
@@ -14,7 +14,7 @@ and uncertainty analysis with Monte Carlo simulations.
 This tool can handle non-coherent fault trees, containing NOT logic.
 .PP
 \fBSCRAM\fP works with PRA models and constructs described
-in OpenPSA Model Exchange Format.
+in the Open-PSA Model Exchange Format.
 .SH OPTIONS
 .TP
 \fB\-\-version\fR
@@ -42,7 +42,7 @@ Perform qualitative analysis with Zero-Suppressed Binary Decision Diagrams
 Perform qualitative analysis with the MOCUS algorithm
 .TP
 \fB\-\-prime\-implicants\fR
-Calcualte prime implicants instead of minimal cut sets
+Calculate prime implicants instead of minimal cut sets
 .TP
 \fB\-\-probability\fR arg
 Perform probability analysis
diff --git a/doc/todo.rst b/doc/todo.rst
index 510ec9a..404e246 100644
--- a/doc/todo.rst
+++ b/doc/todo.rst
@@ -7,7 +7,7 @@ Low Hanging Fruits
 
 - `Issues on GitHub <https://github.com/rakhimov/scram/issues>`_
 - `TODO list in the code <http://scram-pra.org/api/todo.xhtml>`_
-- `Bugs and Issues <https://github.com/rakhimov/scram/blob/develop/bugs.rst>`_
+- `Bugs and Issues <https://github.com/rakhimov/scram/blob/develop/doc/bugs.rst>`_
 
 
 .. note:: The following To-Do items are features with high uncertainties.
@@ -48,7 +48,7 @@ Minor
   Multi-rooted graph analysis. *Low*
 - Importance factor calculation for gates (formulas). *Low*
 - Uncertainty analysis for importance factors. *Moderate*
-- OpenPSA MEF Support:
+- The Open-PSA MEF Support:
 
     * Expressions. *Moderate*
     * "Include directive" in input files to include other input files. *Low*
@@ -60,7 +60,6 @@ Platform Support
 
 - Installation Package for Windows.
 - Installation Package for Mac OS X.
-- Compilation and testing on ARM.
 
 
 Code
diff --git a/doc/xml_comments.rst b/doc/xml_comments.rst
index ebe3a29..c74c6fc 100644
--- a/doc/xml_comments.rst
+++ b/doc/xml_comments.rst
@@ -21,7 +21,7 @@ Recommended Tools
 - `Emacs <http://www.gnu.org/software/emacs/>`_ with
   `nXML mode <http://www.gnu.org/software/emacs/manual/html_mono/nxml-mode.html>`_
 
-- `Notepad++ <http://notepad-plus-plus.org/>`_ with XML Tools plug-in
+- `Notepad++ <https://notepad-plus-plus.org/>`_ with XML Tools plug-in
 
 - `xmllint <http://xmlsoft.org/xmllint.html>`_ with RelaxNG schema
 
diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt
index 2012572..7fff2f1 100644
--- a/gui/CMakeLists.txt
+++ b/gui/CMakeLists.txt
@@ -13,9 +13,11 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
   set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -diag-disable=1875")
 endif()
 
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
+if(Qt5Widgets_VERSION_STRING VERSION_EQUAL "5.7.0")
+  set(CMAKE_CXX_STANDARD 14)  # TODO: Bug in CMake with Qt 5.7.0.
+endif()
 
-include_directories("${PROJECT_SOURCE_DIR}")  # Include the core headers via "src".
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
 
 set(CMAKE_AUTOMOC ON)
 set(CMAKE_AUTOUIC ON)
@@ -25,7 +27,6 @@ set(SCRAM_GUI_RES "${CMAKE_CURRENT_SOURCE_DIR}/res.qrc")
 set(SCRAM_GUI_SRC
   "${CMAKE_CURRENT_SOURCE_DIR}/mainwindow.cpp"
   "${CMAKE_CURRENT_SOURCE_DIR}/event.cpp"
-  "${CMAKE_CURRENT_SOURCE_DIR}/gate.cpp"
   )
 set(SCRAM_GUI_BIN "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp")
 set(SCRAM_GUI_TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/translations")
diff --git a/gui/event.cpp b/gui/event.cpp
index c5bf24f..e185e8e 100644
--- a/gui/event.cpp
+++ b/gui/event.cpp
@@ -21,14 +21,20 @@
 #include <QPainter>
 #include <QPainterPath>
 #include <QRectF>
-#include <QSize>
 #include <QStyleOptionGraphicsItem>
 
 namespace scram {
 namespace gui {
 
-Event::Event(QGraphicsView *view) : m_view(view) {
+template <class T>
+Event::Event(const T &, QGraphicsView *view)
+    : m_view(view), m_typeGraphics(Event::getTypeGraphics<T>(units()))
+{
     m_view->scene()->addItem(this);
+    if (m_typeGraphics) {
+        m_typeGraphics->setParentItem(this);
+        m_typeGraphics->setPos(0, 5.5 * units().height());
+    }
 }
 
 QSize Event::units() const
@@ -37,15 +43,24 @@ QSize Event::units() const
     return {font.averageCharWidth(), font.height()};
 }
 
+void Event::setTypeGraphics(QGraphicsItem *item)
+{
+    delete m_typeGraphics;
+    m_typeGraphics = item;
+    m_typeGraphics->setParentItem(this);
+    m_typeGraphics->setPos(0, 5.5 * units().height());
+}
+
 QRectF Event::boundingRect() const
 {
     int w = units().width();
     int h = units().height();
-    return QRectF(-8 * w, 0, 16 * w, 5.5 * h + 10 * w);
+    return QRectF(-8 * w, 0, 16 * w, 5.5 * h);
 }
 
-void Event::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/,
-                  QWidget */*widget*/)
+void Event::paint(QPainter *painter,
+                  const QStyleOptionGraphicsItem * /*option*/,
+                  QWidget * /*widget*/)
 {
     int w = units().width();
     int h = units().height();
@@ -55,28 +70,25 @@ void Event::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/,
 
     painter->drawLine(QPointF(0, 3 * h), QPointF(0, 4 * h));
 
-    QRectF nameRect(-5 * w, 4 *h, 10 * w, h);
+    QRectF nameRect(-5 * w, 4 * h, 10 * w, h);
     painter->drawRect(nameRect);
     painter->drawText(nameRect, Qt::AlignCenter, m_name);
 
     painter->drawLine(QPointF(0, 5 * h), QPointF(0, 5.5 * h));
 }
 
-void BasicEvent::paint(QPainter *painter,
-                       const QStyleOptionGraphicsItem *option,
-                       QWidget *widget)
+template <>
+QGraphicsItem *Event::getTypeGraphics<BasicEvent>(const QSize &units)
 {
-    Event::paint(painter, option, widget);
-    double r = 5 * units().width();
-    painter->drawEllipse(QPointF(0, 5.5 * units().height() + r), r, r);
+    double r = 5 * units.width();
+    double d = 2 * r;
+    return new QGraphicsEllipseItem(-r, 0, d, d);
 }
 
-void IntermediateEvent::paint(QPainter *painter,
-                              const QStyleOptionGraphicsItem *option,
-                              QWidget *widget)
+BasicEvent::BasicEvent(QGraphicsView *view) : Event(*this, view) {}
+
+IntermediateEvent::IntermediateEvent(QGraphicsView *view) : Event(*this, view)
 {
-    Event::paint(painter, option, widget);
-    m_gate->paint(painter, option);
 }
 
 } // namespace gui
diff --git a/gui/event.h b/gui/event.h
index a3dd2a7..17d5a74 100644
--- a/gui/event.h
+++ b/gui/event.h
@@ -22,6 +22,7 @@
 
 #include <QGraphicsItem>
 #include <QGraphicsView>
+#include <QSize>
 
 #include "gate.h"
 
@@ -30,18 +31,23 @@ namespace gui {
 
 /**
  * @brief The base class for probabilistic events in a fault tree.
+ *
+ * The base event item provides
+ * only the boxes containing the name and description of the event.
+ * A derived class must provide
+ * the symbolic representation of its kind.
+ *
+ * The sizes are measured in units of character height and average width.
+ * This class provides the reference units for derived classes to use.
+ * All derived class shapes should stay within the allowed box limits
+ * to make the fault tree structure layered.
+ *
+ * The derived classes must confine themselves in (10 width x 10 width) box.
  */
 class Event : public QGraphicsItem
 {
 public:
     /**
-     * @brief Assigns an event to a presentation view.
-     *
-     * @param view  The host view.
-     */
-    explicit Event(QGraphicsView *view);
-
-    /**
      * @brief Assigns the short name or ID for the event.
      *
      * @param name  Identifying string name for the event.
@@ -53,7 +59,7 @@ public:
      *         If the name has not been set,
      *         the string is empty.
      */
-    const QString& getName() const { return m_name; }
+    const QString &getName() const { return m_name; }
 
     /**
      * @brief Adds description to the event.
@@ -67,22 +73,67 @@ public:
      * @return Description of the event.
      *         Empty string if no description is provided.
      */
-    const QString& getDescription() { return m_description; }
+    const QString &getDescription() { return m_description; }
 
     QRectF boundingRect() const final;
     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
-               QWidget *widget) override;
+               QWidget *widget) final;
 
 protected:
     /**
+     * @brief Assigns an event to a presentation view.
+     *
+     * The graphical representation of the derived type
+     * is deduced by calling getTypeGraphics.
+     *
+     * @tparam T  The derived class type.
+     *
+     * @param view  The host view.
+     */
+    template <class T> Event(const T &, QGraphicsView *view);
+
+    /**
+     * @brief Provides the graphical representation of the derived type.
+     *
+     * @tparam T  The derived class type.
+     *
+     * @param units  The unit height and width for drawings.
+     *
+     * @return Graphics item to be attached to the event graphics.
+     *         nullptr if the item is undefined upon construction (default).
+     *
+     * @post The item is unowned and allocated on the heap
+     *       in order to be owned by the base event graphics item.
+     */
+    template <class T>
+    static QGraphicsItem *getTypeGraphics(const QSize & /*units*/)
+    {
+        return nullptr;
+    }
+
+    /**
+     * @return The graphics of the derived class.
+     */
+    QGraphicsItem *getTypeGraphics() const { return m_typeGraphics; }
+
+    /**
+     * @brief Releases the current derived class item,
+     *        and sets the new one.
+     *
+     * @param item  The new item to represent the derived type.
+     */
+    void setTypeGraphics(QGraphicsItem *item);
+
+    /**
      * @return Unit width (x) and height (y) for shapes.
      */
     QSize units() const;
 
 private:
-    QGraphicsView *m_view; ///< The host view.
-    QString m_name;        ///< Identifying name of the event.
-    QString m_description; ///< Description of the event.
+    QGraphicsView *m_view;         ///< The host view.
+    QString m_name;                ///< Identifying name of the event.
+    QString m_description;         ///< Description of the event.
+    QGraphicsItem *m_typeGraphics; ///< The graphics of the derived type.
 };
 
 /**
@@ -91,10 +142,10 @@ private:
 class BasicEvent : public Event
 {
 public:
-    using Event::Event;
-
-    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
-               QWidget *widget) override;
+    /**
+     * @param view  The host view.
+     */
+    explicit BasicEvent(QGraphicsView *view);
 };
 
 /**
@@ -103,25 +154,25 @@ public:
 class IntermediateEvent : public Event
 {
 public:
-    using Event::Event;
+    /**
+     * @param view  The host view.
+     */
+    explicit IntermediateEvent(QGraphicsView *view);
 
     /**
      * @brief Sets the Boolean logic for the intermediate event inputs.
      *
      * @param gate  The logic gate of the intermediate event.
      */
-    void setGate(std::unique_ptr<Gate> gate) { m_gate = std::move(gate); }
+    void setGate(std::unique_ptr<Gate> gate)
+    {
+        setTypeGraphics(gate.release());
+    }
 
     /**
      * @return The logic gate of the intermediate event.
      */
-    Gate* getGate() const { return m_gate.get(); }
-
-    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
-               QWidget *widget) override;
-
-private:
-    std::unique_ptr<Gate> m_gate; ///< The logic of the intermediate event.
+    Gate *getGate() const { return static_cast<Gate *>(getTypeGraphics()); }
 };
 
 } // namespace gui
diff --git a/gui/gate.h b/gui/gate.h
index a6123e0..11f6c7b 100644
--- a/gui/gate.h
+++ b/gui/gate.h
@@ -18,8 +18,7 @@
 #ifndef GATE_H
 #define GATE_H
 
-#include <QPainter>
-#include <QStyleOptionGraphicsItem>
+#include <QGraphicsItem>
 
 namespace scram {
 namespace gui {
@@ -27,22 +26,8 @@ namespace gui {
 /**
  * @brief The abstract base class for various gate types.
  */
-class Gate
+class Gate : public QGraphicsItem
 {
-public:
-    Gate(const Gate&) = delete;
-    Gate& operator=(const Gate&) = delete;
-
-    virtual ~Gate() = default;
-
-    /**
-     * @brief Paints the shape of the gate without its inputs.
-     *
-     * @param painter  The reciever of the image.
-     * @param option  Holder of reference units for the sizes.
-     */
-    virtual void paint(QPainter *painter,
-                       const QStyleOptionGraphicsItem *option) = 0;
 };
 
 } // namespace gui
diff --git a/input/EventTreeExample/event_tree.xml b/input/EventTreeExample/event_tree.xml
index 1d1b080..312348a 100644
--- a/input/EventTreeExample/event_tree.xml
+++ b/input/EventTreeExample/event_tree.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <!--
-This is an event tree example taken from OpenPSA MEF description.
+This is an event tree example taken from the Open-PSA MEF description.
 -->
 <opsa-mef>
   <define-event-tree name="my-first-event-tree">
diff --git a/install.py b/install.py
index 342b698..9cb6d8f 100755
--- a/install.py
+++ b/install.py
@@ -43,6 +43,7 @@ def generate_make_files(args):
         sys.exit("CMake could not be found, "
                  "please install CMake before developing SCRAM.")
     cmake_cmd = ["cmake", os.path.abspath(root_dir)]
+    cmake_cmd += ["-DBUILD_SHARED_LIBS=ON"]
     if args.prefix:
         cmake_cmd += ["-DCMAKE_INSTALL_PREFIX=" + absexpanduser(args.prefix)]
 
@@ -52,7 +53,6 @@ def generate_make_files(args):
         cmake_cmd += ["-DCMAKE_BUILD_TYPE=Release"]
     else:
         cmake_cmd += ["-DCMAKE_BUILD_TYPE=Debug"]
-        cmake_cmd += ["--warn-uninitialized"]
         cmake_cmd += ["-Wdev"]
 
     if args.profile:
diff --git a/scripts/fault_tree.py b/scripts/fault_tree.py
index ad07b2b..e2a6a21 100644
--- a/scripts/fault_tree.py
+++ b/scripts/fault_tree.py
@@ -77,13 +77,13 @@ class BasicEvent(Event):
         self.prob = prob
 
     def to_xml(self):
-        """Produces OpenPSA MEF XML definition of the basic event."""
+        """Produces the Open-PSA MEF XML definition of the basic event."""
         return ("<define-basic-event name=\"" + self.name + "\">\n"
                 "<float value=\"" + str(self.prob) + "\"/>\n"
                 "</define-basic-event>\n")
 
-    def to_shorthand(self):
-        """Produces the shorthand definition of the basic event."""
+    def to_aralia(self):
+        """Produces the Aralia definition of the basic event."""
         return "p(" + self.name + ") = " + str(self.prob) + "\n"
 
 
@@ -105,13 +105,13 @@ class HouseEvent(Event):
         self.state = state
 
     def to_xml(self):
-        """Produces OpenPSA MEF XML definition of the house event."""
+        """Produces the Open-PSA MEF XML definition of the house event."""
         return ("<define-house-event name=\"" + self.name + "\">\n"
                 "<constant value=\"" + self.state + "\"/>\n"
                 "</define-house-event>\n")
 
-    def to_shorthand(self):
-        """Produces the shorthand definition of the house event."""
+    def to_aralia(self):
+        """Produces the Aralia definition of the house event."""
         return "s(" + self.name + ") = " + str(self.state) + "\n"
 
 
@@ -194,7 +194,7 @@ class Gate(Event):  # pylint: disable=too-many-instance-attributes
         return ancestors
 
     def to_xml(self, nest=0):
-        """Produces OpenPSA MEF XML definition of the gate.
+        """Produces the Open-PSA MEF XML definition of the gate.
 
         Args:
             nest: The level for nesting formulas of argument gates.
@@ -241,10 +241,10 @@ class Gate(Event):  # pylint: disable=too-many-instance-attributes
         mef_xml += "</define-gate>\n"
         return mef_xml
 
-    def to_shorthand(self):
-        """Produces the shorthand definition of the gate.
+    def to_aralia(self):
+        """Produces the Aralia definition of the gate.
 
-        The transformation to the shorthand format
+        The transformation to the Aralia format
         does not support complement or undefined arguments.
 
         Raises:
@@ -303,7 +303,7 @@ class CcfGroup(object):  # pylint: disable=too-few-public-methods
         self.factors = []
 
     def to_xml(self):
-        """Produces OpenPSA MEF XML definition of the CCF group."""
+        """Produces the Open-PSA MEF XML definition of the CCF group."""
         mef_xml = ("<define-CCF-group name=\"" + self.name + "\""
                    " model=\"" + self.model + "\">\n<members>\n")
         for member in self.members:
@@ -353,7 +353,7 @@ class FaultTree(object):  # pylint: disable=too-many-instance-attributes
         self.non_ccf_events = []  # must be assigned directly.
 
     def to_xml(self, nest=0):
-        """Produces OpenPSA MEF XML definition of the fault tree.
+        """Produces the Open-PSA MEF XML definition of the fault tree.
 
         The fault tree is produced breadth-first.
         The output XML representation is not formatted for human readability.
@@ -391,10 +391,10 @@ class FaultTree(object):  # pylint: disable=too-many-instance-attributes
         mef_xml += "</opsa-mef>\n"
         return mef_xml
 
-    def to_shorthand(self):
-        """Produces the shorthand definition of the fault tree.
+    def to_aralia(self):
+        """Produces the Aralia definition of the fault tree.
 
-        Note that the shorthand format does not support advanced features.
+        Note that the Aralia format does not support advanced features.
         The fault tree must be valid and well formed for printing.
 
         Returns:
@@ -406,13 +406,13 @@ class FaultTree(object):  # pylint: disable=too-many-instance-attributes
         out_txt = self.name + "\n\n"
         sorted_gates = toposort_gates([self.top_gate], self.gates)
         for gate in sorted_gates:
-            out_txt += gate.to_shorthand()
+            out_txt += gate.to_aralia()
         out_txt += "\n"
         for basic_event in self.basic_events:
-            out_txt += basic_event.to_shorthand()
+            out_txt += basic_event.to_aralia()
         out_txt += "\n"
         for house_event in self.house_events:
-            out_txt += house_event.to_shorthand()
+            out_txt += house_event.to_aralia()
         return out_txt
 
 
diff --git a/scripts/fault_tree_generator.py b/scripts/fault_tree_generator.py
index 78de1b8..f4d04ed 100755
--- a/scripts/fault_tree_generator.py
+++ b/scripts/fault_tree_generator.py
@@ -17,8 +17,8 @@
 
 """Generates a fault tree of various complexities.
 
-The generated fault tree can be put into an XML file with the OpenPSA MEF
-or a shorthand format file.
+The generated fault tree can be put into an XML file with the Open-PSA MEF
+or the Aralia format file.
 The resulting fault tree is topologically sorted.
 
 This script helps create complex fault trees in a short time
@@ -40,7 +40,7 @@ all the other factors set by the user are
 guaranteed to be preserved and used as they are.
 """
 
-from __future__ import print_function, division
+from __future__ import print_function, division, absolute_import
 
 from collections import deque
 import random
@@ -578,6 +578,9 @@ def init_gates(gates_queue, common_basic, common_gate, fault_tree):
     max_tries = len(common_gate)  # the number of maximum tries
     num_tries = 0  # the number of tries to get a common gate
 
+    # pylint: disable=too-many-nested-blocks
+    # This code is both hot and coupled for performance reasons.
+    # There may be a better solution than the current approach.
     while gate.num_arguments() < num_arguments:
         s_percent = random.random()  # sample percentage of gates
         s_common = random.random()  # sample the reuse frequency
@@ -885,14 +888,14 @@ def manage_cmd_args(argv=None):
                         default=0, metavar="int")
     parser.add_argument("-o", "--out", type=str, default="fault_tree.xml",
                         metavar="path", help="a file to write the fault tree")
-    parser.add_argument("--shorthand", action="store_true",
-                        help="apply the shorthand format to the output")
+    parser.add_argument("--aralia", action="store_true",
+                        help="apply the Aralia format to the output")
     parser.add_argument("--nest", type=int, default=0, metavar="int",
                         help="nestedness of Boolean formulae in the XML output")
     args = parser.parse_args(argv)
     if args.nest < 0:
         raise ap.ArgumentTypeError("The nesting factor cannot be negative")
-    if args.shorthand:
+    if args.aralia:
         if args.out == "fault_tree.xml":
             args.out = "fault_tree.txt"
     return args
@@ -940,8 +943,8 @@ def main(argv=None):
     factors = setup_factors(args)
     fault_tree = generate_fault_tree(args.ft_name, args.root, factors)
     with open(args.out, "w") as tree_file:
-        if args.shorthand:
-            tree_file.write(fault_tree.to_shorthand())
+        if args.aralia:
+            tree_file.write(fault_tree.to_aralia())
         else:
             write_info(fault_tree, tree_file, args.seed)
             write_summary(fault_tree, tree_file)
diff --git a/scripts/fuzz_tester.py b/scripts/fuzz_tester.py
index eb1a8ab..051f433 100755
--- a/scripts/fuzz_tester.py
+++ b/scripts/fuzz_tester.py
@@ -28,9 +28,9 @@ the script is handy to discover
 complex auto-generated analysis inputs and configurations.
 """
 
-from __future__ import print_function
-
 import hashlib
+import logging
+import multiprocessing
 import os
 import random
 import resource
@@ -73,29 +73,29 @@ class Config(object):
     def configure(args):
         """Adjusts configurations with the cmd-line arguments."""
         if args.cross_validate:
-            print("Cross validating algorithms")
+            logging.info("Cross validating algorithms")
             Config.analysis = [""]
             Config.switch = []
             Config.approximation = [""]
             return
 
         if args.prime_implicants:
-            print("Focusing on Prime Implicants")
+            logging.info("Focusing on Prime Implicants")
             Config.analysis = ["--bdd"]
             Config.approximation = [""]
             Config.additional.append("--prime-implicants")
         elif args.mocus:
-            print("Focusing on MOCUS")
+            logging.info("Focusing on MOCUS")
             Config.analysis = ["--mocus"]
         elif args.bdd:
-            print("Focusing on BDD")
+            logging.info("Focusing on BDD")
             Config.analysis = ["--bdd"]
         elif args.zbdd:
-            print("Focusing on ZBDD")
+            logging.info("Focusing on ZBDD")
             Config.analysis = ["--zbdd"]
 
         if args.preprocessor:
-            print("Focusing on Preprocessor")
+            logging.info("Focusing on Preprocessor")
             Config.restrict()
 
 
@@ -186,7 +186,7 @@ def call_scram(input_file):
         0 for successful runs.
     """
     cmd = generate_analysis_call(input_file)
-    print(cmd)
+    logging.info(cmd)
     cmd += ["--verbosity", "5", "-o", "/dev/null"]
     log_file = open(get_log_file_name(input_file), "w")
     log_file.write(str(cmd) + "\n")
@@ -210,7 +210,7 @@ def cross_validate(input_file):
         1 for failed runs.
     """
     cmd = generate_analysis_call(input_file)
-    print(cmd)
+    logging.info(cmd)
     cmd += ["--print"]
     log_file = open(get_log_file_name(input_file), "w")
     log_file.write(str(cmd) + "\n")
@@ -276,15 +276,19 @@ def main():
                         help="focus on Prime Implicants")
     parser.add_argument("--time-limit", type=int, metavar="seconds",
                         help="CPU time limit for each run")
+    parser.add_argument("-j", "--jobs", type=int, metavar="N",
+                        help="allow N runs (jobs) at once")
     parser.add_argument("-o", "--output-dir", type=str, metavar="path",
                         help="directory to put results")
     args = parser.parse_args()
 
+    logging.basicConfig(level=logging.INFO)
+
     if call(["which", "scram"]):
-        print("SCRAM is not found in the PATH.")
+        logging.error("SCRAM is not found in the PATH.")
         return 2
     if args.output_dir and not os.path.isdir(args.output_dir):
-        print("The output directory doesn't exist.")
+        logging.error("The output directory doesn't exist.")
         return 2
 
     if args.time_limit:
@@ -292,19 +296,41 @@ def main():
                            (args.time_limit, args.time_limit))
 
     Config.configure(args)
-    call_function = cross_validate if args.cross_validate else call_scram
-    ret = 0
-    for i in range(args.num_runs):
-        input_file = generate_input(args.normal, args.coherent, args.output_dir)
-        if call_function(input_file):
-            print("SCRAM failed: " + input_file)
-            ret = 1
-            continue
+    return any(list(get_map(args.jobs)(Fuzzer(args), range(args.num_runs))))
+
+
+def get_map(working_threads):
+    """Returns the map method for jobs."""
+    if working_threads <= 1:
+        return map
+    return multiprocessing.Pool(processes=working_threads).imap_unordered
+
+
+class Fuzzer(object):  # pylint: disable=too-few-public-methods
+    """Runs fuzz testing."""
+
+    def __init__(self, args):
+        """Saves the argument for later use."""
+        self.args = args
+        self.call_function = (cross_validate
+                              if args.cross_validate else call_scram)
+
+    def __call__(self, job_number):
+        """Returns 1 for failure and 0 for success."""
+        input_file = generate_input(self.args.normal, self.args.coherent,
+                                    self.args.output_dir)
+        num_runs = job_number + 1
+        if self.call_function(input_file):
+            logging.info("SCRAM failed run " + str(num_runs) + ": " +
+                         input_file)
+            return 1
         os.remove(input_file)
         os.remove(get_log_file_name(input_file))
-        if not (i + 1) % 10:
-            print("\n========== Finished run #%d ==========\n" % (i + 1))
-    return ret
+        if not num_runs % 10:
+            logging.info(
+                "\n========== Finished run #" + str(num_runs) + " ==========\n")
+        return 0
+
 
 if __name__ == "__main__":
     sys.exit(main())
diff --git a/scripts/nqueens.py b/scripts/nqueens.py
index 8497473..9291938 100755
--- a/scripts/nqueens.py
+++ b/scripts/nqueens.py
@@ -17,7 +17,7 @@
 
 """Generates a fault tree representation of the N Queens problem.
 
-The representation is given in the shorthand format.
+The representation is given in the Aralia format.
 """
 
 from __future__ import print_function
@@ -62,20 +62,24 @@ def gate(i, j=None):
 
 def print_constraints(n):  # pylint: disable=invalid-name
     """Prints the main setup constraints for n queens."""
+    def _append_attacked_positions(i, j, logic):
+        """Appends positions attacked by the (i, j) queen into logic."""
+        for k in range(1, n + 1):
+            if k != j:
+                logic.append(position(i, k, True))
+            if k != i:
+                logic.append(position(k, j, True))
+                diag_one = j + k - i
+                if diag_one > 0 and diag_one <= n:
+                    logic.append(position(k, diag_one, True))
+                diag_two = j + i - k
+                if diag_two > 0 and diag_two <= n:
+                    logic.append(position(k, diag_two, True))
+
     for i in range(1, n + 1):
         for j in range(1, n + 1):
             logic = [position(i, j, False)]
-            for k in range(1, n + 1):
-                if k != j:
-                    logic.append(position(i, k, True))
-                if k != i:
-                    logic.append(position(k, j, True))
-                    diag_one = j + k - i
-                    if diag_one > 0 and diag_one <= n:
-                        logic.append(position(k, diag_one, True))
-                    diag_two = j + i - k
-                    if diag_two > 0 and diag_two <= n:
-                        logic.append(position(k, diag_two, True))
+            _append_attacked_positions(i, j, logic)
             print(gate(i, j) + " := " + " & ".join(logic))
 
 
diff --git a/scripts/shorthand_to_xml.py b/scripts/shorthand_to_xml.py
deleted file mode 100755
index b8ca6ac..0000000
--- a/scripts/shorthand_to_xml.py
+++ /dev/null
@@ -1,527 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2014-2016 Olzhas Rakhimov
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-"""Converts the shorthand notation for fault trees into an XML file.
-
-The output file is formatted according to the OpenPSA MEF.
-The default output file name is the input file name with the XML extension.
-
-The shorthand notation is described as follows:
-AND gate:                          gate_name := (arg1 & arg2 & ...)
-OR gate:                           gate_name := (arg1 | arg2 | ...)
-ATLEAST(k/n) gate:                 gate_name := @(k, [arg1, arg2, ...])
-NOT gate:                          gate_name := ~(arg)
-XOR gate:                          gate_name := (arg1 ^ arg2)
-NULL gate:                         gate_name := arg
-Probability of a basic event:      p(event_name) = probability
-Boolean state of a house event:    s(event_name) = state
-
-Some requirements and additions to the shorthand format:
-1. The names and references are not case-sensitive
-   and must be formatted according to 'XML NCNAME datatype'
-   without double dashes('--'), period('.'), and trailing '-'.
-2. Arguments can be complemented with '~'.
-3. Undefined arguments are processed as 'events' to the final XML output.
-   Only warnings are emitted in the case of undefined events.
-4. Name clashes or redefinitions are errors.
-5. Cycles in the graph are detected by the script as errors.
-6. The top gate is detected by the script.
-   Only one top gate is allowed
-   unless otherwise specified by the user.
-7. Repeated arguments are considered an error.
-8. The script is flexible with whitespace characters in the input file.
-9. Parentheses are optional for logical operators except for ATLEAST.
-"""
-
-from __future__ import print_function
-
-import os
-import re
-import sys
-
-import argparse as ap
-
-from fault_tree import Event, BasicEvent, HouseEvent, Gate, FaultTree
-
-
-class ParsingError(Exception):
-    """General parsing errors."""
-
-    pass
-
-
-class FormatError(Exception):
-    """Common errors in writing the shorthand format."""
-
-    pass
-
-
-class FaultTreeError(Exception):
-    """Indication of problems in the fault tree."""
-
-    pass
-
-
-class LateBindingGate(Gate):
-    """Representation of a gate with arguments defined late or not at all.
-
-    Attributes:
-        event_arguments: String names of arguments.
-    """
-
-    def __init__(self, name, operator=None, k_num=None):
-        """Initializes a gate.
-
-        Args:
-            name: Identifier of the event.
-            operator: Boolean operator of this formula.
-            k_num: Min number for the combination operator.
-        """
-        super(LateBindingGate, self).__init__(name, operator, k_num)
-        self.event_arguments = []
-
-    def num_arguments(self):
-        """Returns the number of arguments."""
-        return len(self.event_arguments)
-
-
-class LateBindingFaultTree(FaultTree):
-    """Representation of a fault tree for shorthand to XML purposes.
-
-    Attributes:
-        multi_top: A flag to indicate to allow multiple top gates.
-    """
-
-    def __init__(self, name=None, multi_top=False):
-        """Initializes an empty fault tree.
-
-        Args:
-            name: The name of the system described by the fault tree container.
-            multi_top: A flag to indicate multi-rooted container.
-        """
-        super(LateBindingFaultTree, self).__init__(name)
-        self.multi_top = multi_top
-        self.__gates = {}
-        self.__basic_events = {}
-        self.__house_events = {}
-        self.__undef_events = {}
-
-    def __check_redefinition(self, name):
-        """Checks if an event is being redefined.
-
-        Args:
-            name: The name under investigation.
-
-        Raises:
-            FaultTreeError: The given name already exists.
-        """
-        if (name.lower() in self.__basic_events or
-                name.lower() in self.__gates or
-                name.lower() in self.__house_events):
-            raise FaultTreeError("Redefinition of an event: " + name)
-
-    def __visit(self, gate):
-        """Recursively visits the given gate sub-tree to detect a cycle.
-
-        Upon visiting the descendant gates,
-        their marks are changed from temporary to permanent.
-
-        Args:
-            gate: The current gate.
-
-        Returns:
-            None if no cycle is found.
-            A list of event names in a detected cycle path in reverse order.
-        """
-        if not gate.mark:
-            gate.mark = "temp"
-            for child in gate.g_arguments:
-                cycle = self.__visit(child)
-                if cycle:
-                    cycle.append(gate.name)
-                    return cycle
-            gate.mark = "perm"
-        elif gate.mark == "temp":
-            return [gate.name]  # a cycle is detected
-        return None  # the permanent mark
-
-    @staticmethod
-    def __raise_cycle(cycle):
-        """Prints the detected cycle with the error.
-
-        Args:
-            cycle: A list of gate names in the cycle path in reverse order.
-
-        Raises:
-            FaultTreeError: Error with a message containing the cycle.
-        """
-        start = cycle[0]
-        cycle.reverse()  # print top-down
-        raise FaultTreeError("Detected a cycle: " +
-                             "->".join(cycle[cycle.index(start):]))
-
-    def __detect_cycle(self):
-        """Checks if the fault tree has a cycle.
-
-        Raises:
-            FaultTreeError: There is a cycle in the fault tree.
-        """
-        assert self.top_gates is not None
-        for top_gate in self.top_gates:
-            cycle = self.__visit(top_gate)
-            if cycle:
-                LateBindingFaultTree.__raise_cycle(cycle)
-
-        detached_gates = [x for x in self.gates if not x.mark]
-        if detached_gates:
-            error_msg = "Detected detached gates that may be in a cycle\n"
-            error_msg += str([x.name for x in detached_gates])
-            try:
-                for gate in detached_gates:
-                    cycle = self.__visit(gate)
-                    if cycle:
-                        LateBindingFaultTree.__raise_cycle(cycle)
-            except FaultTreeError as error:
-                error_msg += "\n" + str(error)
-                raise FaultTreeError(error_msg)
-
-    def __detect_top(self):
-        """Detects the top gate of the developed fault tree.
-
-        Raises:
-            FaultTreeError: Multiple or no top gates are detected.
-        """
-        top_gates = [x for x in self.gates if x.is_orphan()]
-        if len(top_gates) > 1 and not self.multi_top:
-            names = [x.name for x in top_gates]
-            raise FaultTreeError("Detected multiple top gates:\n" + str(names))
-        elif not top_gates:
-            raise FaultTreeError("No top gate is detected")
-        self.top_gates = top_gates
-
-    def add_basic_event(self, name, prob):
-        """Creates and adds a new basic event into the fault tree.
-
-        Args:
-            name: A name for the new basic event.
-            prob: The probability of the new basic event.
-
-        Raises:
-            FaultTreeError: The given name already exists.
-        """
-        self.__check_redefinition(name)
-        event = BasicEvent(name, prob)
-        self.__basic_events.update({name.lower(): event})
-        self.basic_events.append(event)
-
-    def add_house_event(self, name, state):
-        """Creates and adds a new house event into the fault tree.
-
-        Args:
-            name: A name for the new house event.
-            state: The state of the new house event ("true" or "false").
-
-        Raises:
-            FaultTreeError: The given name already exists.
-        """
-        self.__check_redefinition(name)
-        event = HouseEvent(name, state)
-        self.__house_events.update({name.lower(): event})
-        self.house_events.append(event)
-
-    def add_gate(self, name, operator, arguments, k_num=None):
-        """Creates and adds a new gate into the fault tree.
-
-        Args:
-            name: A name for the new gate.
-            operator: A gate operator for the new gate.
-            arguments: Collection of argument event names of the new gate.
-            k_num: K number is required for a combination type of a gate.
-
-        Raises:
-            FaultTreeError: The given name already exists.
-        """
-        self.__check_redefinition(name)
-        gate = LateBindingGate(name, operator, k_num)
-        gate.event_arguments = arguments
-        self.__gates.update({name.lower(): gate})
-        self.gates.append(gate)
-
-    def populate(self):
-        """Assigns arguments to gates and parents to arguments.
-
-        Raises:
-            FaultTreeError: There are problems with the fault tree.
-        """
-        for gate in self.gates:
-            assert gate.num_arguments() > 0
-            for event_arg in gate.event_arguments:
-                complement = event_arg.startswith("~")
-                event_name = event_arg.lstrip("~").lower()
-                if event_name in self.__gates:
-                    gate.add_argument(self.__gates[event_name], complement)
-                elif event_name in self.__basic_events:
-                    gate.add_argument(self.__basic_events[event_name],
-                                      complement)
-                elif event_name in self.__house_events:
-                    gate.add_argument(self.__house_events[event_name],
-                                      complement)
-                elif event_name in self.__undef_events:
-                    gate.add_argument(self.__undef_events[event_name],
-                                      complement)
-                else:
-                    print("Warning. Unidentified event: " + event_name)
-                    event_node = Event(event_name)
-                    self.__undef_events.update({event_name: event_node})
-                    gate.add_argument(event_node, complement)
-
-        for basic_event in self.basic_events:
-            if basic_event.is_orphan():
-                print("Warning. Orphan basic event: " + basic_event.name)
-        for house_event in self.house_events:
-            if house_event.is_orphan():
-                print("Warning. Orphan house event: " + house_event.name)
-        self.__detect_top()
-        self.__detect_cycle()
-
-    def undefined_events(self):
-        """Returns list of undefined events."""
-        return self.__undef_events.values()
-
-
-# Pattern for names and references
-_NAME_SIG = r"[a-zA-Z]\w*(-\w+)*"
-_LITERAL = r"~?" + _NAME_SIG
-_RE_FT_NAME = re.compile(r"^(" + _NAME_SIG + r")$")  # Fault tree name
-# Probability description for a basic event
-_RE_PROB = re.compile(r"^p\(\s*(?P<name>" + _NAME_SIG +
-                      r")\s*\)\s*=\s*(?P<prob>1|0|0\.\d+)$")
-# State description for a house event
-_RE_STATE = re.compile(r"^s\(\s*(?P<name>" + _NAME_SIG +
-                       r")\s*\)\s*=\s*(?P<state>true|false)$")
-# General gate name and pattern
-_GATE_SIG = r"^(?P<name>" + _NAME_SIG + r")\s*:=\s*"
-_RE_GATE = re.compile(_GATE_SIG + r"(?P<formula>.+)$")
-# Optional parentheses for formulas
-_RE_PAREN = re.compile(r"\(([^()]+)\)$")
-# Gate type identifications
-_RE_AND = re.compile(r"(" + _LITERAL + r"(\s*&\s*" + _LITERAL + r"\s*)+)$")
-_RE_OR = re.compile(r"(" + _LITERAL + r"(\s*\|\s*" + _LITERAL + r"\s*)+)$")
-_VOTE_ARGS = r"\[(\s*" + _LITERAL + r"(\s*,\s*" + _LITERAL + r"\s*){2,})\]"
-_RE_VOTE = re.compile(r"@\(\s*([2-9])\s*,\s*" + _VOTE_ARGS + r"\s*\)\s*$")
-_RE_XOR = re.compile(r"(" + _LITERAL + r"\s*\^\s*" + _LITERAL + r")$")
-_RE_NOT = re.compile(r"~\(\s*(" + _LITERAL + r")\s*\)$")
-_RE_NULL = re.compile(r"(" + _LITERAL + r")$")
-
-
-def get_arguments(arguments_string, splitter):
-    """Splits the input string into arguments of a formula.
-
-    Args:
-        arguments_string: String contaning arguments.
-        splitter: Splitter specific to the operator, i.e. "&", "|", ','.
-
-    Returns:
-        arguments list from the input string.
-
-    Raises:
-        FaultTreeError: Repeated arguments for the formula.
-    """
-    arguments = arguments_string.strip().split(splitter)
-    arguments = [x.strip() for x in arguments]
-    if len(arguments) > len(set([x.lower() for x in arguments])):
-        raise FaultTreeError("Repeated arguments:\n" + arguments_string)
-    return arguments
-
-
-def get_formula(line):
-    """Constructs formula from the given line.
-
-    Args:
-        line: A string containing a Boolean equation.
-
-    Returns:
-        A formula operator, arguments, and k_num.
-
-    Raises:
-        ParsingError: Parsing is unsuccessful.
-        FormatError: Formatting problems in the input.
-        FaultTreeError: Problems in the structure of the formula.
-    """
-    line = line.strip()
-    if _RE_PAREN.match(line):
-        line = _RE_PAREN.match(line).group(1).strip()
-    arguments = None
-    operator = None
-    k_num = None
-    if _RE_OR.match(line):
-        arguments = _RE_OR.match(line).group(1)
-        arguments = get_arguments(arguments, "|")
-        operator = "or"
-    elif _RE_XOR.match(line):
-        arguments = _RE_XOR.match(line).group(1)
-        arguments = get_arguments(arguments, "^")
-        operator = "xor"
-    elif _RE_AND.match(line):
-        arguments = _RE_AND.match(line).group(1)
-        arguments = get_arguments(arguments, "&")
-        operator = "and"
-    elif _RE_VOTE.match(line):
-        k_num, arguments = _RE_VOTE.match(line).group(1, 2)
-        arguments = get_arguments(arguments, ",")
-        if int(k_num) >= len(arguments):
-            raise FaultTreeError(
-                "Invalid k/n for the combination formula:\n" + line)
-        operator = "atleast"
-    elif _RE_NOT.match(line):
-        arguments = _RE_NOT.match(line).group(1)
-        arguments = [arguments.strip()]
-        operator = "not"
-    elif _RE_NULL.match(line):
-        arguments = _RE_NULL.match(line).group(1)
-        arguments = [arguments.strip()]
-        operator = "null"  # pass-through
-    else:
-        raise ParsingError("Cannot interpret the formula:\n" + line)
-    return operator, arguments, k_num
-
-
-def interpret_line(line, fault_tree):
-    """Interprets a line from the shorthand format input.
-
-    Args:
-        line: The line in the shorthand format.
-        fault_tree: The fault tree container to update.
-
-    Raises:
-        ParsingError: Parsing is unsuccessful.
-        FormatError: Formatting problems in the input.
-        FaultTreeError: Problems in the structure of the fault tree.
-    """
-    line = line.strip()
-    if not line:
-        return
-    if _RE_GATE.match(line):
-        gate_name, formula_line = _RE_GATE.match(line).group("name", "formula")
-        operator, arguments, k_num = get_formula(formula_line)
-        fault_tree.add_gate(gate_name, operator, arguments, k_num)
-    elif _RE_PROB.match(line):
-        event_name, prob = _RE_PROB.match(line).group("name", "prob")
-        fault_tree.add_basic_event(event_name, prob)
-    elif _RE_STATE.match(line):
-        event_name, state = _RE_STATE.match(line).group("name", "state")
-        fault_tree.add_house_event(event_name, state)
-    elif _RE_FT_NAME.match(line):
-        if fault_tree.name:
-            raise FormatError("Redefinition of the fault tree name:\n%s to %s" %
-                              (fault_tree.name, line))
-        fault_tree.name = _RE_FT_NAME.match(line).group(1)
-    else:
-        raise ParsingError("Cannot interpret the line.")
-
-
-def parse_input(shorthand_file, multi_top=False):
-    """Parses an input file with a shorthand description of a fault tree.
-
-    Args:
-        shorthand_file: The input file open for reads.
-        multi_top: If the input contains a fault tree with multiple top gates.
-
-    Returns:
-        The fault tree described in the input file.
-
-    Raises:
-        ParsingError: Parsing is unsuccessful.
-        FormatError: Formatting problems in the input.
-        FaultTreeError: Problems in the structure of the fault tree.
-    """
-    fault_tree = LateBindingFaultTree()
-    assert fault_tree.name is None
-    line_num = 0
-    line = None
-    try:
-        for line in shorthand_file:
-            line_num += 1
-            interpret_line(line, fault_tree)
-    except ParsingError as err:
-        raise ParsingError(str(err) + "\nIn line %d:\n" % line_num + line)
-    except FormatError as err:
-        raise FormatError(str(err) + "\nIn line %d:\n" % line_num + line)
-    except FaultTreeError as err:
-        raise FaultTreeError(str(err) + "\nIn line %d:\n" % line_num + line)
-    if fault_tree.name is None:
-        raise FormatError("The fault tree name is not given.")
-    fault_tree.multi_top = multi_top
-    fault_tree.populate()
-    return fault_tree
-
-
-def main(argv=None):
-    """Verifies arguments and calls parser and writer.
-
-    Args:
-        argv: An optional list containing the command-line arguments.
-            If None, the command-line arguments from sys will be used.
-
-    Raises:
-        ArgumentTypeError: Problemns with the arguments.
-        IOError: Input or output files are not accessible.
-        ParsingError: Problems parsing the input file.
-        FormatError: Formatting issues in the input.
-        FaultTreeError: The input fault tree is malformed.
-    """
-    description = "Shorthand => OpenPSA MEF XML Converter"
-    parser = ap.ArgumentParser(description=description)
-    parser.add_argument("input_file", type=str,
-                        help="input file with the shorthand notation")
-    parser.add_argument("--multi-top", help="multiple top events",
-                        action="store_true")
-    parser.add_argument("-o", "--out",
-                        help="output file to write the converted input")
-    args = parser.parse_args(argv)
-
-    fault_tree = None
-    with open(args.input_file, "r") as shorthand_file:
-        fault_tree = parse_input(shorthand_file, args.multi_top)
-
-    out = args.out
-    if not out:
-        out = os.path.basename(args.input_file)
-        out = out[:out.rfind(".")] + ".xml"
-
-    with open(out, "w") as tree_file:
-        tree_file.write("<?xml version=\"1.0\"?>\n")
-        tree_file.write(fault_tree.to_xml())
-
-if __name__ == "__main__":
-    try:
-        main()
-    except ap.ArgumentTypeError as err:
-        print("Argument Error:\n" + str(err))
-        sys.exit(2)
-    except IOError as err:
-        print("IO Error:\n" + str(err))
-        sys.exit(1)
-    except ParsingError as err:
-        print("Parsing Error:\n" + str(err))
-        sys.exit(1)
-    except FormatError as err:
-        print("Format Error:\n" + str(err))
-        sys.exit(1)
-    except FaultTreeError as err:
-        print("Error in the fault tree:\n" + str(err))
-        sys.exit(1)
diff --git a/scripts/test_fault_tree_generator.py b/scripts/test/test_fault_tree_generator.py
similarity index 93%
rename from scripts/test_fault_tree_generator.py
rename to scripts/test/test_fault_tree_generator.py
index c8e6b1f..103850d 100644
--- a/scripts/test_fault_tree_generator.py
+++ b/scripts/test/test_fault_tree_generator.py
@@ -15,7 +15,7 @@
 
 """Tests for the fault tree generator."""
 
-from __future__ import division
+from __future__ import division, absolute_import
 
 import random
 from subprocess import call
@@ -121,7 +121,7 @@ class FaultTreeGeneratorTestCase(TestCase):
 
     def setUp(self):
         """Initializes the generator factors for default complexity."""
-        self.output = NamedTemporaryFile()
+        self.output = NamedTemporaryFile(mode="w+")
         random.seed(123)
         self.factors = Factors()
         self.factors.set_min_max_prob(0.01, 0.1)
@@ -148,18 +148,18 @@ class FaultTreeGeneratorTestCase(TestCase):
             doc = etree.parse(test_file)
             assert_true(relaxng.validate(doc))
 
-    def test_shorthand_output(self):
-        """Checks if the shorthand format output passes validation."""
+    def test_aralia_output(self):
+        """Checks if the Aralia format output passes validation."""
         self.factors.set_gate_weights([1, 1, 1, 0.1, 0.1])
         self.factors.num_house = 10
         self.factors.num_ccf = 10
         self.factors.calculate()
         fault_tree = generate_fault_tree("TestingTree", "root", self.factors)
         assert_is_not_none(fault_tree)
-        self.output.write(fault_tree.to_shorthand())
+        self.output.write(fault_tree.to_aralia())
         self.output.file.flush()
-        tmp = NamedTemporaryFile()
-        cmd = ["./shorthand_to_xml.py", self.output.name, "-o", tmp.name]
+        tmp = NamedTemporaryFile(mode="w+")
+        cmd = ["./translators/aralia.py", self.output.name, "-o", tmp.name]
         assert_equal(0, call(cmd))
 
     def test_constrain_num_gates(self):
@@ -175,7 +175,7 @@ class FaultTreeGeneratorTestCase(TestCase):
 
 def test_main():
     """Tests the main() of the generator."""
-    tmp = NamedTemporaryFile()
+    tmp = NamedTemporaryFile(mode="w+")
     main(["-b", "200", "-g", "200", "-o", tmp.name])
     relaxng_doc = etree.parse("../share/input.rng")
     relaxng = etree.RelaxNG(relaxng_doc)
@@ -183,6 +183,7 @@ def test_main():
         doc = etree.parse(test_file)
         assert_true(relaxng.validate(doc))
 
-    main(["-b", "200", "-g", "200", "-o", tmp.name, "--shorthand"])
-    cmd = ["./shorthand_to_xml.py", tmp.name, "-o", NamedTemporaryFile().name]
+    main(["-b", "200", "-g", "200", "-o", tmp.name, "--aralia"])
+    cmd = ["./translators/aralia.py", tmp.name, "-o",
+           NamedTemporaryFile(mode="w+").name]
     assert_equal(0, call(cmd))
diff --git a/scripts/test_shorthand_to_xml.py b/scripts/test_shorthand_to_xml.py
deleted file mode 100644
index b2d38c9..0000000
--- a/scripts/test_shorthand_to_xml.py
+++ /dev/null
@@ -1,427 +0,0 @@
-# Copyright (C) 2014-2016 Olzhas Rakhimov
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-"""Tests for the shorthand-to-XML converter."""
-
-import os
-from tempfile import NamedTemporaryFile
-from unittest import TestCase
-
-from lxml import etree
-from nose.tools import assert_raises, assert_is_not_none, assert_equal, \
-    assert_true
-
-from shorthand_to_xml import ParsingError, FormatError, FaultTreeError, \
-    parse_input, main
-
-
-def parse_input_file(name, multi_top=False):
-    """Calls the input file parser to get the fault tree."""
-    with open(name) as shorthand_file:
-        return parse_input(shorthand_file, multi_top)
-
-
-def test_correct():
-    """Tests the valid overall process."""
-    tmp = NamedTemporaryFile()
-    tmp.write("ValidFaultTree\n\n")
-    tmp.write("root := g1 | g2 | g3 | g4 | g7 | e1\n")
-    tmp.write("g1 := e2 & g3 & g5\n")
-    tmp.write("g2 := h1 & g6\n")
-    tmp.write("g3 := (g6 ^ e2)\n")
-    tmp.write("g4 := @(2, [g5, e3, e4])\n")
-    tmp.write("g5 := ~(e3)\n")
-    tmp.write("g6 := (e3 | e4)\n\n")
-    tmp.write("g7 := g8\n\n")
-    tmp.write("g8 := ~e2 & ~e3\n\n")
-    tmp.write("p(e1) = 0.1\n")
-    tmp.write("p(e2) = 0.2\n")
-    tmp.write("p(e3) = 0.3\n")
-    tmp.write("s(h1) = true\n")
-    tmp.write("s(h2) = false\n")
-    tmp.flush()
-    fault_tree = parse_input_file(tmp.name)
-    assert_is_not_none(fault_tree)
-    yield assert_equal, 9, len(fault_tree.gates)
-    yield assert_equal, 3, len(fault_tree.basic_events)
-    yield assert_equal, 2, len(fault_tree.house_events)
-    yield assert_equal, 1, len(fault_tree.undefined_events())
-    out = NamedTemporaryFile()
-    out.write("<?xml version=\"1.0\"?>\n")
-    out.write(fault_tree.to_xml())
-    out.flush()
-    relaxng_doc = etree.parse("../share/input.rng")
-    relaxng = etree.RelaxNG(relaxng_doc)
-    with open(out.name, "r") as test_file:
-        doc = etree.parse(test_file)
-        assert_true(relaxng.validate(doc))
-
-
-def test_ft_name_redefinition():
-    """Tests the redefinition of the fault tree name."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FaultTreeName\n")
-    tmp.write("AnotherFaultTree\n")
-    tmp.write("g1 := e1\n")
-    tmp.flush()
-    assert_raises(FormatError, parse_input_file, tmp.name)
-
-
-def test_ncname_ft():
-    """The name of the fault tree must conform to NCNAME format."""
-    tmp = NamedTemporaryFile()
-    tmp.write("Contains Whitespace Characters\n")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("Peri.od\n")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("EndWithDash-\n")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("Double--Dash\n")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("42StartWithNumbers\n")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("Correct-Name_42\n")
-    tmp.write("g1 := e1 & e2\n")  # dummy gate
-    tmp.flush()
-    yield parse_input_file, tmp.name
-
-
-def test_no_ft_name():
-    """Tests the case where no fault tree name is provided."""
-    tmp = NamedTemporaryFile()
-    tmp.write("g1 := g2 & e1\n")
-    tmp.write("g2 := h1 & e1\n")
-    tmp.flush()
-    assert_raises(FormatError, parse_input_file, tmp.name)
-
-
-def test_illegal_format():
-    """Test Arithmetic operators."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := g2 + e1\n")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := g2 * e1\n")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := -e1\n")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := g2 / e1\n")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-
-
-def test_repeated_argument():
-    """Tests the formula with a repeated argument."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := g2 & e1\n")
-    tmp.write("g2 := E1 & e1\n")  # repeated argument with uppercase
-    tmp.flush()
-    assert_raises(FaultTreeError, parse_input_file, tmp.name)
-
-
-def test_missing_parenthesis():
-    """Tests cases with a missing opening or closing parentheses."""
-    tmp = NamedTemporaryFile()
-    tmp.write("WrongParentheses\n")
-    tmp.write("g1 := a | b)")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("WrongParentheses\n")
-    tmp.write("g1 := (a | b")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-
-
-def test_nested_parentheses():
-    """Tests cases with nested parentheses."""
-    tmp = NamedTemporaryFile()
-    tmp.write("WrongParentheses\n")
-    tmp.write("g1 := ((a | b))")
-    tmp.flush()
-    yield assert_raises, ParsingError, parse_input_file, tmp.name
-
-
-def test_vote_gate_arguments():
-    """K/N or Combination gate/operator should have its K < its N."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := @(3, [a, b, c])")  # K = N
-    tmp.flush()
-    yield assert_raises, FaultTreeError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := @(4, [a, b, c])")  # K > N
-    tmp.flush()
-    yield assert_raises, FaultTreeError, parse_input_file, tmp.name
-
-
-def test_null_gate():
-    """Tests if NULL type gates are recognized correctly."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := a")
-    tmp.flush()
-    fault_tree = parse_input_file(tmp.name)
-    assert_is_not_none(fault_tree)
-    yield assert_equal, 1, len(fault_tree.gates)
-    yield assert_equal, "g1", fault_tree.gates[0].name
-    yield assert_true, "a" in fault_tree.gates[0].event_arguments
-    yield assert_equal, "null", fault_tree.gates[0].operator
-
-
-def test_not_gate():
-    """Tests if NOT type gates are recognized correctly."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := ~(a)")
-    tmp.flush()
-    fault_tree = parse_input_file(tmp.name)
-    assert_is_not_none(fault_tree)
-    yield assert_equal, 1, len(fault_tree.gates)
-    yield assert_equal, "g1", fault_tree.gates[0].name
-    yield assert_true, "a" in fault_tree.gates[0].event_arguments
-    yield assert_equal, "not", fault_tree.gates[0].operator
-
-
-def test_no_top_event():
-    """Detection of cases without top gate definitions.
-
-    Note that this also means that there is a cycle that includes the root.
-    """
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := g2 & e1\n")
-    tmp.write("g2 := g1 & e1\n")
-    tmp.flush()
-    assert_raises(FaultTreeError, parse_input_file, tmp.name)
-
-
-def test_multi_top():
-    """Multiple root events without the flag causes a problem by default."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := e2 & e1\n")
-    tmp.write("g2 := h1 & e1\n")
-    tmp.flush()
-    yield assert_raises, FaultTreeError, parse_input_file, tmp.name
-    yield assert_is_not_none, parse_input_file(tmp.name, True)  # with the flag
-
-
-def test_redefinition():
-    """Tests name collision detection of events."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := g2 & e1\n")
-    tmp.write("g2 := h1 & e1\n")
-    tmp.write("g2 := e2 & e1\n")  # redefining an event
-    tmp.flush()
-    assert_raises(FaultTreeError, parse_input_file, tmp.name)
-
-
-def test_orphan_events():
-    """Tests cases with orphan house and basic event events."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := g2 & e1\n")
-    tmp.write("g2 := h1 & e1\n")
-    tmp.write("p(e1) = 0.5\n")
-    tmp.write("s(h1) = false\n")
-    tmp.flush()
-    yield assert_is_not_none, parse_input_file(tmp.name)
-    tmp.write("p(e2) = 0.1\n")  # orphan basic event
-    tmp.flush()
-    yield assert_is_not_none, parse_input_file(tmp.name)
-    tmp.write("s(h2) = true\n")  # orphan house event
-    tmp.flush()
-    yield assert_is_not_none, parse_input_file(tmp.name)
-
-
-def test_cycle_detection():
-    """Tests cycles in the fault tree."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := g2 & e1\n")
-    tmp.write("g2 := g3 & e1\n")
-    tmp.write("g3 := g2 & e1\n")  # cycle
-    tmp.flush()
-    yield assert_raises, FaultTreeError, parse_input_file, tmp.name
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := u1 & g2 & e1\n")
-    tmp.write("g2 := u2 & g3 & e1\n")  # nested formula cycle
-    tmp.write("g3 := u3 & g2 & e1\n")  # cycle
-    tmp.flush()
-    yield assert_raises, FaultTreeError, parse_input_file, tmp.name
-
-
-def test_detached_gates():
-    """Some cycles may get detached from the original fault tree."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := e2 & e1\n")
-    tmp.write("g2 := g3 & e1\n")  # detached gate
-    tmp.write("g3 := g2 & e1\n")  # cycle
-    tmp.flush()
-    assert_raises(FaultTreeError, parse_input_file, tmp.name)
-
-
-class ComplementArgTestCase(TestCase):
-    """Complement arguments of gates."""
-
-    def setUp(self):
-        """Launches a temporary file."""
-        self.tmp = NamedTemporaryFile()
-        self.tmp.write("FT\n")
-
-    def check_gate(self, symbol, operator, custom_gate=None):
-        """Default g1 gate test with e2 as a complement argument."""
-        if custom_gate:
-            self.tmp.write(custom_gate)
-        else:
-            self.tmp.write("g1 := e1 %s ~e2\n" % symbol)
-        self.tmp.flush()
-        fault_tree = parse_input_file(self.tmp.name)
-        assert_is_not_none(fault_tree)
-        assert_equal(1, len(fault_tree.gates))
-        gate = fault_tree.gates[0]
-        assert_equal("g1", gate.name)
-        assert_equal(operator, gate.operator)
-        if not custom_gate:
-            assert_true("e1" in gate.event_arguments)
-        assert_true("~e2" in gate.event_arguments)
-        assert_equal(1, len(gate.complement_arguments))
-        assert_equal("e2", [x.name for x in gate.complement_arguments][0])
-
-    def test_or(self):
-        """OR formula with complement arguments."""
-        self.check_gate("|", "or")
-
-    def test_xor(self):
-        """XOR formula with complement arguments."""
-        self.check_gate("^", "xor")
-
-    def test_and(self):
-        """AND Formula with complement arguments."""
-        self.check_gate("&", "and")
-
-    def test_vote(self):
-        """Combination with complement arguments."""
-        self.check_gate("@", "atleast", "g1 := @(2, [e1, ~e2, e3])")
-
-    def test_null(self):
-        """NULL with a single complement argument."""
-        self.check_gate("", "null", "g1 := ~e2")
-
-    def test_not(self):
-        """NOT of a complement argument."""
-        self.check_gate("", "not", "g1 := ~(~e2)")
-
-    def test_cancellation(self):
-        """Supplies argument and its complement."""
-        self.check_gate("&", "and", "g1 := ~e2 & e2")
-
-
-class NestedFormulaTestCase(TestCase):
-    """Nested logical operator tests."""
-
-    def setUp(self):
-        """Launches a temporary file."""
-        self.tmp = NamedTemporaryFile()
-        self.tmp.write("FT\n")
-
-    def test_or_xor(self):
-        """Formula with OR and XOR operators."""
-        self.tmp.write("g1 := e1 | e2 ^ e3\n")
-        self.tmp.flush()
-        assert_raises(ParsingError, parse_input_file, self.tmp.name)
-
-    def test_or_and(self):
-        """Formula with OR and AND operators."""
-        self.tmp.write("g1 := e1 | e2 & e3\n")
-        self.tmp.flush()
-        assert_raises(ParsingError, parse_input_file, self.tmp.name)
-
-    def test_or_vote(self):
-        """Formula with OR and K/N operators."""
-        self.tmp.write("g1 := e1 | @(2, [e2, e3, e4])\n")
-        self.tmp.flush()
-        assert_raises(ParsingError, parse_input_file, self.tmp.name)
-
-    def test_xor_xor(self):
-        """Formula with XOR and XOR operators.
-
-        Note that this is a special case
-        because most analysis restricts XOR operator to two arguments,
-        so nested formula of XOR operators must be created.
-        """
-        self.tmp.write("g1 := e1 ^ e2 ^ e3\n")
-        self.tmp.flush()
-        assert_raises(ParsingError, parse_input_file, self.tmp.name)
-
-    def test_xor_and(self):
-        """Formula with XOR and AND operators."""
-        self.tmp.write("g1 := e1 ^ e2 & e3\n")
-        self.tmp.flush()
-        assert_raises(ParsingError, parse_input_file, self.tmp.name)
-
-    def test_not_not(self):
-        """Formula with NOT and NOT operators.
-
-        This is a special case. It is considered an error without parentheses.
-        """
-        self.tmp.write("g1 := ~~e1\n")
-        self.tmp.flush()
-        assert_raises(ParsingError, parse_input_file, self.tmp.name)
-        tmp = NamedTemporaryFile()
-        tmp.write("FT\n")
-        tmp.write("g1 := ~e1~a\n")
-        tmp.flush()
-        assert_raises(ParsingError, parse_input_file, tmp.name)
-
-
-def test_main():
-    """Tests the main function."""
-    tmp = NamedTemporaryFile()
-    tmp.write("FT\n")
-    tmp.write("g1 := g2 & e1\n")
-    tmp.write("g2 := g3 & e1\n")
-    tmp.write("g3 := e2 & e1\n")
-    tmp.flush()
-    main([tmp.name])
-    out = os.path.basename(tmp.name)
-    out = out[:out.rfind(".")] + ".xml"
-    assert_true(os.path.exists(out))
-    os.remove(out)
diff --git a/share/config.rng b/share/config.rng
index 4ee85ad..c8dbf0a 100644
--- a/share/config.rng
+++ b/share/config.rng
@@ -5,11 +5,11 @@
     <element name="config">
       <element name="input-files">
         <oneOrMore>
-          <element name="file"> <data type="string"/> </element>
+          <element name="file"> <data type="anyURI"/> </element>
         </oneOrMore>
       </element>
       <optional>
-        <element name="output-path"> <data type="string"/> </element>
+        <element name="output-path"> <data type="anyURI"/> </element>
       </optional>
       <ref name="options"/>
     </element>
@@ -20,9 +20,11 @@
       <optional>
         <element name="algorithm">
           <attribute name="name">
-            <data type="string">
-              <param name="pattern">mocus|bdd|zbdd</param>
-            </data>
+            <choice>
+              <value>mocus</value>
+              <value>bdd</value>
+              <value>zbdd</value>
+            </choice>
           </attribute>
         </element>
       </optional>
@@ -33,24 +35,16 @@
         <element name="analysis">
           <interleave>
             <optional>
-              <attribute name="probability">
-                <data type="boolean"/>
-              </attribute>
+              <attribute name="probability"> <data type="boolean"/> </attribute>
             </optional>
             <optional>
-              <attribute name="importance">
-                <data type="boolean"/>
-              </attribute>
+              <attribute name="importance"> <data type="boolean"/> </attribute>
             </optional>
             <optional>
-              <attribute name="uncertainty">
-                <data type="boolean"/>
-              </attribute>
+              <attribute name="uncertainty"> <data type="boolean"/> </attribute>
             </optional>
             <optional>
-              <attribute name="ccf">
-                <data type="boolean"/>
-              </attribute>
+              <attribute name="ccf"> <data type="boolean"/> </attribute>
             </optional>
           </interleave>
         </element>
@@ -58,54 +52,45 @@
       <optional>
         <element name="approximation">
           <attribute name="name">
-            <data type="string">
-              <param name="pattern">rare-event|mcub</param>
-            </data>
+            <choice>
+              <value>rare-event</value>
+              <value>mcub</value>
+            </choice>
           </attribute>
         </element>
       </optional>
       <optional>
-        <element name="limits">
-          <interleave>
-            <optional>
-              <element name="product-order">
-                <data type="nonNegativeInteger"/>
-              </element>
-            </optional>
-            <optional>
-              <element name="mission-time">
-                <data type="double"/>
-              </element>
-            </optional>
-            <optional>
-              <element name="cut-off">
-                <data type="double"/>
-              </element>
-            </optional>
-            <optional>
-              <element name="number-of-trials">
-                <data type="nonNegativeInteger"/>
-              </element>
-            </optional>
-            <optional>
-              <element name="number-of-quantiles">
-                <data type="nonNegativeInteger"/>
-              </element>
-            </optional>
-            <optional>
-              <element name="number-of-bins">
-                <data type="nonNegativeInteger"/>
-              </element>
-            </optional>
-            <optional>
-              <element name="seed">
-                <data type="nonNegativeInteger"/>
-              </element>
-            </optional>
-          </interleave>
-        </element>
+        <ref name="limits"/>
       </optional>
     </element>
   </define>
 
+  <define name="limits">
+    <element name="limits">
+      <interleave>
+        <optional>
+          <element name="product-order"> <data type="nonNegativeInteger"/> </element>
+        </optional>
+        <optional>
+          <element name="mission-time"> <data type="double"/> </element>
+        </optional>
+        <optional>
+          <element name="cut-off"> <data type="double"/> </element>
+        </optional>
+        <optional>
+          <element name="number-of-trials"> <data type="nonNegativeInteger"/> </element>
+        </optional>
+        <optional>
+          <element name="number-of-quantiles"> <data type="nonNegativeInteger"/> </element>
+        </optional>
+        <optional>
+          <element name="number-of-bins"> <data type="nonNegativeInteger"/> </element>
+        </optional>
+        <optional>
+          <element name="seed"> <data type="nonNegativeInteger"/> </element>
+        </optional>
+      </interleave>
+    </element>
+  </define>
+
 </grammar>
diff --git a/share/input.rng b/share/input.rng
index 847246c..012a079 100644
--- a/share/input.rng
+++ b/share/input.rng
@@ -60,7 +60,7 @@
 
   <define name="NonEmptyString">  <!-- Texts without LF and other special chars. -->
     <data type="normalizedString">
-      <param name="pattern">.*\S+.*</param>
+      <param name="minLength">1</param>
     </data>
   </define>
 
diff --git a/share/open-psa/curves.bnf b/share/open-psa/curves.bnf
deleted file mode 100644
index 26fd94e..0000000
--- a/share/open-psa/curves.bnf
+++ /dev/null
@@ -1,11 +0,0 @@
-curve ::=
-  <curve
-    [ name="identifier" ]
-    [ description="text" ]
-    [ X-title="string" Y-title="string" [ Z-title="string" ] ]
-    [ X-unit="unit" Y-unit="unit" [ Z-unit="unit" ] ]
-  >
-    <point X="float" Y="float" [ Z="float" ] />*
-  </curve>
-
-unit ::= seconds | hours | ...
diff --git a/share/open-psa/mcs.bnf b/share/open-psa/mcs.bnf
deleted file mode 100644
index ddf085a..0000000
--- a/share/open-psa/mcs.bnf
+++ /dev/null
@@ -1,18 +0,0 @@
-sum-of-products ::=
-  <sum-of-products
-    [ name="identifier" ]
-    [ description="text" ]
-    [ basic-events="integer" ]
-    [ products="integer" ]
-  >
-    product*
-  </sum-of-products>
-
-product ::=
-  <product [ order="integer" ]>
-    literal*
-  </product>
-
-literal ::=
-    <basic-event name="identifier"/>
-  | <not> <basic-event name="identifier"/> </not>
diff --git a/share/open-psa/mef.dtd b/share/open-psa/mef.dtd
deleted file mode 100644
index 5d28186..0000000
--- a/share/open-psa/mef.dtd
+++ /dev/null
@@ -1,461 +0,0 @@
-<!--
-     WARNING: This DTD will fail to validate Boolean operations
-        involving AND, OR, NOT due to the redefinition conflict
-        with Formulae AND, OR, NOT.
--->
-
-<!-- Advance declaration of ENTITIES -->
-
-<!-- IV.3. Formulae -->
-<!ENTITY % formula
-    "(event | gate | house-event | basic-event | constant
-| and | or | not | xor | iff | nand | nor | atleast | cardinality)">
-
-
-<!-- V.2.1. Entities -->
-<!ENTITY % value "(bool | int | float)">
-<!ENTITY % numerical-operation
-    "(neg | add | sub | mul | div | pi | abs | acos | asin | atan | cos
-| cosh | exp | log | log10 | mod | pow | sin | sinh | tan | tanh
-| sqrt | ceil | floor | min | max | mean)">
-<!ENTITY % Boolean-operation "(bool_not | bool_and | bool_or | eq | df
-| lt | gt | leq | geq)">
-<!ENTITY % conditional-operation "(ite | switch)">
-<!ENTITY % operation
-    "(%numerical-operation; | %Boolean-operation; | %conditional-operation;)">
-<!ENTITY % built-in
-    "(exponential | GLM | Weibull | periodic-test | extern-function)">
-<!ENTITY % random-deviate
-    "(uniform-deviate | normal-deviate | lognormal-deviate | gamma-deviate
-| beta-deviate | histogram)">
-<!ENTITY % test-event "(test-initiating-event | test-functional-event)">
-<!ENTITY % expression
-    "(%value; | parameter | system-mission-time | %operation; | %built-in;
-| %random-deviate; | %test-event;)">
-
-<!-- II.3. Instructions, Rules -->
-
-<!ENTITY % set "(set-gate | set-house-event | set-basic-event | set-parameter)">
-<!ENTITY % collect "(collect-formula | collect-expression)">
-<!ENTITY % instruction "(%set; | %collect; | if | block | rule | event-tree)">
-
-
-<!-- I. Calculation Layer -->
-
-<!-- I.1. Models -->
-
-<!ELEMENT opsa-mef
-    (label?, attributes?,
-     (
-      define-event-tree
-      | define-alignment
-      | define-consequence-group | define-consequence
-      | define-rule
-      | define-initiating-event-group | define-initiating-event
-      | define-fault-tree
-      | define-substitution
-      | define-CCF-group
-      | include
-      )*,
-     model-data?
-     )
->
-
-<!ELEMENT label (#PCDATA)>
-
-<!ELEMENT attributes (attribute*)>
-<!ELEMENT attribute EMPTY>
-<!ATTLIST attribute
-    name CDATA #REQUIRED
-    value CDATA #REQUIRED
-    type CDATA #IMPLIED
->
-
-<!ELEMENT include EMPTY>
-<!ATTLIST include file CDATA #REQUIRED>
-
-
-<!-- I.2. Consequences, Consequence Groups -->
-
-<!ELEMENT define-consequence (label?, attributes?, initiating-event, sequence)>
-<!ATTLIST define-consequence name CDATA #REQUIRED>
-
-<!ELEMENT define-consequence-group
-    (label?, attributes?, (consequence | consequence-group)*)>
-<!ATTLIST define-consequence-group name CDATA #REQUIRED>
-
-<!ELEMENT consequence EMPTY>
-<!ATTLIST consequence name CDATA #REQUIRED>
-
-<!ELEMENT consequence-group EMPTY>
-<!ATTLIST consequence-group name CDATA #REQUIRED>
-
-<!ELEMENT sequence EMPTY>
-<!ATTLIST sequence name CDATA #REQUIRED>
-
-
-<!-- I.3. Missions, Phases -->
-
-<!ELEMENT define-alignment (label?, attributes?, (%instruction;)*)>
-<!ATTLIST define-alignment
-    name CDATA #REQUIRED
-    time-fraction CDATA #REQUIRED
->
-
-
-<!-- II. Event Tree Layer -->
-
-<!-- II.1. Initiating events, Initiating event Groups -->
-
-<!ENTITY % collected-item "(basic-event | gate | parameter)">
-
-<!ELEMENT define-initiating-event
-    (label?, attributes?, (%collected-item; | consequence | consequence-group))>
-<!ATTLIST define-initiating-event name CDATA #REQUIRED>
-
-<!ELEMENT define-initiating-event-group
-    (label?, attributes?, (initiating-event | initiating-event-group)+)>
-<!ATTLIST define-initiating-event-group name CDATA #REQUIRED>
-
-<!ELEMENT initiating-event EMPTY>
-<!ATTLIST initiating-event
-    name CDATA #REQUIRED
-    event-tree CDATA #IMPLIED
->
-
-<!ELEMENT initiating-event-group EMPTY>
-<!ATTLIST initiating-event-group
-    name CDATA #REQUIRED
-    event-tree CDATA #IMPLIED
->
-
-
-<!-- II.2. Event Trees -->
-
-<!ENTITY % end-state "(sequence | branch)">
-<!ENTITY % branch "((%instruction;)*, (fork | %end-state;))">
-
-<!ELEMENT define-event-tree
-    (label?, attributes?,
-     define-functional-event*,
-     define-sequence*,
-     define-branch*,
-     initial-state)
->
-<!ATTLIST define-event-tree name CDATA #REQUIRED>
-
-<!ELEMENT define-functional-event (label?, attributes?)>
-<!ATTLIST define-functional-event name CDATA #REQUIRED>
-
-<!ELEMENT define-sequence (label?, attributes?, (%instruction;)+)>
-<!ATTLIST define-sequence name CDATA #REQUIRED>
-
-<!ELEMENT define-branch (label?, attributes?, %branch;)>
-<!ATTLIST define-branch name CDATA #REQUIRED>
-
-<!ELEMENT fork (path)+>
-<!ATTLIST fork functional-event CDATA #REQUIRED>
-
-<!ELEMENT path (%branch;)>
-<!ATTLIST path state CDATA #REQUIRED>
-
-<!ELEMENT initial-state (%branch;)>
-
-<!ELEMENT branch EMPTY>
-<!ATTLIST branch name CDATA #REQUIRED>
-
-
-<!-- II.3. Instructions, Rules -->
-
-<!ENTITY % directions "(forward | backward | both)">
-
-<!ELEMENT set-gate (%formula;)>
-<!ATTLIST set-gate
-    name CDATA #REQUIRED
-    direction (directions) #IMPLIED
->
-
-<!ELEMENT set-house-event (constant)>
-<!ATTLIST set-house-event
-    name CDATA #REQUIRED
-    direction (directions) #IMPLIED
->
-
-<!ELEMENT set-basic-event (%expression;)>
-<!ATTLIST set-basic-event
-    name CDATA #REQUIRED
-    direction (directions) #IMPLIED
->
-
-<!ELEMENT set-parameter (%expression;)>
-<!ATTLIST set-parameter
-    name CDATA #REQUIRED
-    direction (directions) #IMPLIED
->
-
-<!ELEMENT if (%expression;, %instruction;, (%instruction;)?)>
-<!ELEMENT collect-formula (%formula;)>
-<!ELEMENT collect-expression (%expression;)>
-<!ELEMENT block ((%instruction;)*)>
-
-<!ELEMENT event-tree EMPTY>
-<!ATTLIST event-tree name CDATA #REQUIRED>
-
-<!ELEMENT rule EMPTY>
-<!ATTLIST rule name CDATA #REQUIRED>
-
-<!ELEMENT define-rule (label?, attributes?, (%instruction;)+)>
-<!ATTLIST define-rule name CDATA #REQUIRED>
-
-
-<!-- III. Meta-Logical Layer -->
-
-<!-- III.1. CCF-Groups -->
-
-<!ELEMENT define-CCF-group
-    (label?, attributes?, members, distribution, (factor | factors))>
-<!ATTLIST define-CCF-group
-    name CDATA #REQUIRED
-    model (beta-factor | MGL | alpha-factor | phi-factor) #REQUIRED
->
-
-<!ELEMENT members (basic-event+)>
-<!ELEMENT factors (factor+)>
-
-<!ELEMENT factor (%expression;)>
-<!ATTLIST factor level CDATA #REQUIRED>
-
-
-<!-- III.2. Substitutions -->
-
-<!ELEMENT distribution (%expression;)>
-<!ELEMENT define-substitution
-    (label?, attributes?, hypothesis, source?, target)>
-<!ATTLIST define-substitution
-    name CDATA #IMPLIED
-    type CDATA #IMPLIED
->
-
-<!ELEMENT hypothesis (%formula;)>
-<!ELEMENT source (basic-event+)>
-<!ELEMENT target (basic-event+ | %formula;)>
-
-
-<!-- IV. Fault Tree Layer -->
-
-<!-- IV.1. Definitions of Fault Trees & Components -->
-
-<!ELEMENT define-fault-tree
-    (label?, attributes?,
-     (
-      define-substitution | define-CCF-group
-      | define-component
-      | define-gate | define-house-event
-      | define-basic-event | define-parameter
-      | include
-      )*
-     )
->
-<!ATTLIST define-fault-tree name CDATA #REQUIRED>
-
-<!ELEMENT define-component
-    (label?, attributes?,
-     (
-      define-substitution | define-CCF-group
-      | define-component
-      | define-gate | define-house-event
-      | define-basic-event | define-parameter
-      | include
-      )*
-     )
->
-<!ATTLIST define-component
-    name CDATA #REQUIRED
-    role (private | public) #IMPLIED
->
-
-<!ELEMENT model-data
-    (define-house-event | define-basic-event | define-parameter | include)*>
-
-
-<!-- IV.2. Definitions of Gates, House Events & Basic Events -->
-
-<!ELEMENT define-gate (label?, attributes?, %formula;)>
-<!ATTLIST define-gate
-    name CDATA #REQUIRED
-    role (private | public) #IMPLIED
->
-
-<!ELEMENT define-house-event (label?, attributes?, constant?)>
-<!ATTLIST define-house-event
-    name CDATA #REQUIRED
-    role (private | public) #IMPLIED
->
-
-<!ELEMENT define-basic-event (label?, attributes?, (%expression;)?)>
-<!ATTLIST define-basic-event
-    name CDATA #REQUIRED
-    role (private | public) #IMPLIED
->
-
-
-<!-- IV.3. Formulae -->
-
-<!ENTITY % event-type "(gate | house-event | basic-event)">
-
-<!ELEMENT event EMPTY>
-<!ATTLIST event
-    name CDATA #REQUIRED
-    type %event-type; #IMPLIED
->
-
-<!ELEMENT gate EMPTY>
-<!ATTLIST gate name CDATA #REQUIRED>
-
-<!ELEMENT house-event EMPTY>
-<!ATTLIST house-event name CDATA #REQUIRED>
-
-<!ELEMENT basic-event EMPTY>
-<!ATTLIST basic-event name CDATA #REQUIRED>
-
-<!ELEMENT and ((%formula;)+)>
-<!ELEMENT or ((%formula;)+)>
-<!ELEMENT not (%formula;)>
-<!ELEMENT xor ((%formula;)+)>
-<!ELEMENT iff ((%formula;)+)>
-<!ELEMENT nand ((%formula;)+)>
-<!ELEMENT nor ((%formula;)+)>
-<!ELEMENT atleast ((%formula;)+)>
-<!ATTLIST atleast min CDATA #REQUIRED>
-
-<!ELEMENT cardinality ((%formula;)+)>
-<!ATTLIST cardinality min CDATA #REQUIRED max CDATA #REQUIRED>
-
-<!ELEMENT imply (%formula;, %formula;)>
-
-<!ELEMENT constant EMPTY>
-<!ATTLIST constant value (true | false) #REQUIRED>
-
-
-<!-- V. Stochastic Layer -->
-
-<!-- V.1. Definition of Parameters -->
-
-<!ENTITY % units
-    "(bool | int | float | hours | hours-1 | years | years-1 | fit | demands)">
-<!ELEMENT define-parameter (label?, attributes?, %expression;)>
-<!ATTLIST define-parameter
-    name CDATA #REQUIRED
-    role (private | public) #IMPLIED
-    unit %units; #IMPLIED
->
-
-
-<!-- V.2. Expressions -->
-
-<!-- V.2.1. Entities -->
-
-<!-- V.2.2. Constants, Parameters -->
-
-<!ELEMENT bool EMPTY>
-<!ATTLIST bool value (true | false) #REQUIRED>
-
-<!ELEMENT int EMPTY>
-<!ATTLIST int value CDATA #REQUIRED>
-
-<!ELEMENT float EMPTY>
-<!ATTLIST float value CDATA #REQUIRED>
-
-<!ELEMENT system-mission-time EMPTY>
-<!ATTLIST system-mission-time unit %units; #IMPLIED>
-
-<!ELEMENT parameter EMPTY>
-<!ATTLIST parameter
-    name CDATA #REQUIRED
-    unit %units; #IMPLIED
->
-
-
-<!-- V.2.3. Numerical Expressions -->
-
-<!ELEMENT neg (%expression;)>
-<!ELEMENT add ((%expression;)+)>
-<!ELEMENT sub ((%expression;)+)>
-<!ELEMENT mul ((%expression;)+)>
-<!ELEMENT div ((%expression;)+)>
-<!ELEMENT pi EMPTY>
-<!ELEMENT abs (%expression;)>
-<!ELEMENT acos (%expression;)>
-<!ELEMENT asin (%expression;)>
-<!ELEMENT atan (%expression;)>
-<!ELEMENT cos (%expression;)>
-<!ELEMENT cosh (%expression;)>
-<!ELEMENT exp (%expression;)>
-<!ELEMENT log (%expression;)>
-<!ELEMENT log10 (%expression;)>
-<!ELEMENT mod (%expression;, %expression;)>
-<!ELEMENT pow (%expression;, %expression;)>
-<!ELEMENT sin (%expression;)>
-<!ELEMENT sinh (%expression;)>
-<!ELEMENT tan (%expression;)>
-<!ELEMENT tanh (%expression;)>
-<!ELEMENT sqrt (%expression;)>
-<!ELEMENT ceil (%expression;)>
-<!ELEMENT floor (%expression;)>
-<!ELEMENT min ((%expression;)+)>
-<!ELEMENT max ((%expression;)+)>
-<!ELEMENT mean ((%expression;)+)>
-
-
-<!-- V.2.4. Boolean Expressions -->
-
-<!-- NOTE: Boolean AND, OR, NOT are renamed to avoid redefinition. -->
-<!ELEMENT bool_not (%expression;)>
-<!ELEMENT bool_and ((%expression;)+)>
-<!ELEMENT bool_or ((%expression;)+)>
-<!ELEMENT eq (%expression;, %expression;)>
-<!ELEMENT df (%expression;, %expression;)>
-<!ELEMENT lt (%expression;, %expression;)>
-<!ELEMENT gt (%expression;, %expression;)>
-<!ELEMENT leq (%expression;, %expression;)>
-<!ELEMENT geq (%expression;, %expression;)>
-
-
-<!-- V.2.5. Conditional Expressions -->
-
-<!ELEMENT ite (%expression;, %expression;, %expression;)>
-<!ELEMENT switch (case*, %expression;)>
-<!ELEMENT case (%expression;, %expression;)>
-
-
-<!-- V.2.6. Built-ins -->
-
-<!ELEMENT exponential (%expression;, %expression;)>
-<!ELEMENT GLM (%expression;, %expression;, %expression;, %expression;)>
-<!ELEMENT Weibull (%expression;, %expression;, %expression;, %expression;)>
-<!ELEMENT periodic-test ((%expression;)+)>
-<!ELEMENT extern-function ((%expression;)*)>
-<!ATTLIST extern-function name CDATA #REQUIRED>
-
-
-<!-- V.2.7. Random-Deviates -->
-
-<!ELEMENT uniform-deviate (%expression;, %expression;)>
-<!ELEMENT normal-deviate (%expression;, %expression;)>
-<!ELEMENT lognormal-deviate (%expression;, %expression;, %expression;)>
-<!ELEMENT gamma-deviate (%expression;, %expression;)>
-<!ELEMENT beta-deviate (%expression;, %expression;)>
-<!ELEMENT histogram (%expression;, bin+)>
-<!ELEMENT bin (%expression;, %expression;)>
-
-
-<!-- V.2.8. Test-Events -->
-
-<!ELEMENT test-initiating-event EMPTY>
-<!ATTLIST test-initiating-event name CDATA #REQUIRED>
-
-<!ELEMENT test-functional-event EMPTY>
-<!ATTLIST test-functional-event
-    name CDATA #REQUIRED
-    state CDATA #REQUIRED
->
diff --git a/share/open-psa/mef.rnc b/share/open-psa/mef.rnc
deleted file mode 100644
index f0eee9f..0000000
--- a/share/open-psa/mef.rnc
+++ /dev/null
@@ -1,539 +0,0 @@
-# ###############################################################
-
-# I. Calculation Layer
-
-# ###############################################################
-
-# =============================================================
-
-# I.1. Models
-
-# =============================================================
-start =
-  element opsa-mef {
-    name?,
-    label?,
-    attributes?,
-    (event-tree-definition
-     | alignment-definition
-     | consequence-group-definition
-     | consequence-definition
-     | rule-definition
-     | initiating-event-group-definition
-     | initiating-event-definition
-     | fault-tree-definition
-     | substitution-definition
-     | CCF-group-definition
-     | include-directive)*,
-    element model-data {
-      (house-event-definition
-       | basic-event-definition
-       | parameter-definition
-       | include-directive)*
-    }?
-  }
-Identifier = xsd:NCName { pattern = "[^\-.]+(-[^\-.]+)*" }
-name = attribute name { Identifier }
-reference =
-  attribute name {
-    xsd:NCName {
-      pattern = "([^\-.]+(-[^\-.]+)*)(\.\i[^\-.]*(-[^\-.]+)*)*"
-    }
-  }
-label = element label { text }
-attributes =
-  element attributes {
-    element attribute {
-      name,
-      attribute value { xsd:string },
-      attribute type { xsd:string }?
-    }*
-  }
-include-directive =
-  element include {
-    attribute file { xsd:string }
-  }
-# =============================================================
-
-# I.2. Consequences, Consequence Groups
-
-# =============================================================
-consequence-definition =
-  element define-consequence {
-    name,
-    label?,
-    attributes?,
-    element initiating-event { name },
-    element sequence { name }
-  }
-consequence-group-definition =
-  element define-consequence-group {
-    name, label?, attributes?, (consequence | consequence-group)
-  }
-consequence = element consequence { name }
-consequence-group = element consequence-group { name }
-# =============================================================
-
-# I.3. Missions, Phases
-
-# =============================================================
-alignment-definition =
-  element define-alignment {
-    name, label?, attributes?, phase-definition+
-  }
-phase-definition =
-  element define-phase {
-    name,
-    attribute time-fraction { xsd:float },
-    label?,
-    attributes?,
-    instruction*
-  }
-# ###############################################################
-
-# II. Event Tree Layer
-
-# ###############################################################
-
-# =============================================================
-
-# II.1. Initiating events, Initiating event Groups
-
-# =============================================================
-initiating-event-definition =
-  element define-initiating-event {
-    name,
-    attribute event-tree { Identifier }?,
-    label?,
-    attributes?,
-    (collected-item | consequence | consequence-group)?
-  }
-initiating-event-group-definition =
-  element define-initiating-event-group {
-    name,
-    attribute event-tree { Identifier }?,
-    label?,
-    attributes?,
-    initiating-event+
-  }
-initiating-event =
-  element initiating-event { name }
-  | element initiating-event-group { name }
-collected-item = basic-event | gate | parameter
-# =============================================================
-
-# II.2. Event Trees
-
-# =============================================================
-event-tree-definition =
-  element define-event-tree {
-    name,
-    label?,
-    attributes?,
-    functional-event-definition*,
-    sequence-definition*,
-    branch-definition*,
-    initial-state
-  }
-functional-event-definition =
-  element define-functional-event { name, label?, attributes? }
-sequence-definition =
-  element define-sequence { name, label?, attributes?, instruction+ }
-branch-definition =
-  element define-branch { name, label?, attributes?, branch }
-initial-state = element initial-state { branch }
-branch = instruction*, (fork | end-state)
-fork =
-  element fork {
-    attribute functional-event { Identifier },
-    path+
-  }
-path =
-  element path {
-    attribute state { Identifier },
-    branch
-  }
-end-state =
-  element sequence { name }
-  | element branch { name }
-# =============================================================
-
-# II.3. Instructions, Rules
-
-# =============================================================
-instruction = set | collect | if-then-else | block | rule | link
-set = set-gate | set-house-event | set-basic-event | set-parameter
-set-gate =
-  element set-gate {
-    name,
-    attribute direction { direction }?,
-    formula
-  }
-set-house-event =
-  element set-house-event {
-    name,
-    attribute direction { direction }?,
-    Boolean-constant
-  }
-set-basic-event =
-  element set-basic-event {
-    name,
-    attribute direction { direction }?,
-    expression
-  }
-set-parameter =
-  element set-parameter {
-    name,
-    attribute direction { direction }?,
-    expression
-  }
-direction = "forward" | "backward" | "both"
-if-then-else = element if { expression, instruction, instruction? }
-collect = collect-formula | collect-expression
-collect-formula = element collect-formula { formula }
-collect-expression = element collect-expression { expression }
-block = element block { instruction* }
-rule = element rule { name }
-link = element event-tree { name }
-rule-definition =
-  element define-rule { name, label?, attributes?, instruction+ }
-# ###############################################################
-
-# III. Meta-Logical Layer
-
-# ###############################################################
-
-# =============================================================
-
-# III.1. CCF-Groups
-
-# =============================================================
-CCF-group-definition =
-  element define-CCF-group {
-    name,
-    attribute model { CCF-model },
-    label?,
-    attributes?,
-    members,
-    distribution,
-    factors
-  }
-members = element members { basic-event+ }
-factors =
-  element factors { factor+ }
-  | factor
-factor =
-  element factor {
-    attribute level { xsd:nonNegativeInteger }?,
-    expression
-  }
-distribution = element distribution { expression }
-CCF-model = "beta-factor" | "MGL" | "alpha-factor" | "phi-factor"
-# =============================================================
-
-# III.2. Substitutions
-
-# =============================================================
-substitution-definition =
-  element define-substitution {
-    name?,
-    attribute type { xsd:string }?,
-    label?,
-    attributes?,
-    element hypothesis { formula },
-    element source { basic-event+ }?,
-    element target { basic-event+ | Boolean-constant }
-  }
-# ###############################################################
-
-# IV. Fault Tree Layer
-
-# ###############################################################
-
-# =============================================================
-
-# IV.1. Definitions of Fault Trees & Components
-
-# =============================================================
-fault-tree-definition =
-  element define-fault-tree {
-    name,
-    label?,
-    attributes?,
-    (substitution-definition
-     | CCF-group-definition
-     | event-definition
-     | component-definition
-     | parameter-definition
-     | include-directive)*
-  }
-component-definition =
-  element define-component {
-    name,
-    role?,
-    label?,
-    attributes?,
-    (substitution-definition
-     | CCF-group-definition
-     | event-definition
-     | component-definition
-     | parameter-definition
-     | include-directive)*
-  }
-role = attribute role { "private" | "public" }
-event-definition =
-  gate-definition | house-event-definition | basic-event-definition
-# =============================================================
-
-# IV.2. Definitions of Gates, House Events & Basic Events
-
-# =============================================================
-gate-definition =
-  element define-gate { name, role?, label?, attributes?, formula }
-house-event-definition =
-  element define-house-event {
-    name, role?, label?, attributes?, Boolean-constant?
-  }
-basic-event-definition =
-  element define-basic-event {
-    name, role?, label?, attributes?, expression?
-  }
-# =============================================================
-
-# IV.3. Formulae
-
-# =============================================================
-formula =
-  event
-  | Boolean-constant
-  | element and { formula+ }
-  | element or { formula+ }
-  | element not { formula }
-  | element xor { formula+ }
-  | element iff { formula+ }
-  | element nand { formula+ }
-  | element nor { formula+ }
-  | element atleast {
-      attribute min { xsd:nonNegativeInteger },
-      formula+
-    }
-  | element cardinality {
-      attribute min { xsd:nonNegativeInteger },
-      attribute max { xsd:nonNegativeInteger },
-      formula+
-    }
-  | element imply { formula, formula }
-event =
-  element event {
-    reference,
-    attribute type { event-type }?
-  }
-  | gate
-  | house-event
-  | basic-event
-event-type = "gate" | "basic-event" | "house-event"
-gate = element gate { reference }
-house-event = element house-event { reference }
-basic-event = element basic-event { reference }
-Boolean-constant =
-  element constant {
-    attribute value { Boolean-value }
-  }
-Boolean-value = "true" | "false"
-# ###############################################################
-
-# V. Stochastic Layer
-
-# ###############################################################
-
-# =============================================================
-
-# V.1. Definition of Parameters
-
-# =============================================================
-parameter-definition =
-  element define-parameter {
-    name,
-    role?,
-    attribute unit { units }?,
-    label?,
-    attributes?,
-    expression
-  }
-units =
-  "bool"
-  | "int"
-  | "float"
-  | "hours"
-  | "hours-1"
-  | "years"
-  | "years-1"
-  | "fit"
-  | "demands"
-# =============================================================
-
-# V.2. Expressions
-
-# =============================================================
-
-# ***********************************************************
-
-# V.2.1. Entities
-
-# ***********************************************************
-expression =
-  constant
-  | parameter
-  | operation
-  | built-in
-  | random-deviate
-  | test-event
-constant = bool | int | float
-parameter =
-  element parameter {
-    reference,
-    attribute unit { units }?
-  }
-  | element system-mission-time {
-      attribute unit { units }?
-    }
-operation =
-  numerical-operation | Boolean-operation | conditional-operation
-built-in = exponential | GLM | Weibull | periodic-test | extern-function
-random-deviate =
-  uniform-deviate
-  | normal-deviate
-  | lognormal-deviate
-  | gamma-deviate
-  | beta-deviate
-  | histogram
-test-event = test-initiating-event | test-functional-event
-# ***********************************************************
-
-# V.2.2. Constants, Parameters
-
-# ***********************************************************
-bool =
-  element bool {
-    attribute value { Boolean-value }
-  }
-int =
-  element int {
-    attribute value { xsd:integer }
-  }
-float =
-  element float {
-    attribute value { xsd:float }
-  }
-# ***********************************************************
-
-# V.2.3. Numerical Expressions
-
-# ***********************************************************
-numerical-operation =
-  element neg { expression }
-  | element add { expression+ }
-  | element sub { expression+ }
-  | element mul { expression+ }
-  | element div { expression+ }
-  | element pi { empty }
-  | element abs { expression }
-  | element acos { expression }
-  | element asin { expression }
-  | element atan { expression }
-  | element cos { expression }
-  | element cosh { expression }
-  | element exp { expression }
-  | element log { expression }
-  | element log10 { expression }
-  | element mod { expression, expression }
-  | element pow { expression, expression }
-  | element sin { expression }
-  | element sinh { expression }
-  | element tan { expression }
-  | element tanh { expression }
-  | element sqrt { expression }
-  | element ceil { expression }
-  | element floor { expression }
-  | element min { expression+ }
-  | element max { expression+ }
-  | element mean { expression+ }
-# ***********************************************************
-
-# V.2.4. Boolean Expressions
-
-# ***********************************************************
-Boolean-operation =
-  element not { expression }
-  | element and { expression+ }
-  | element or { expression+ }
-  | element eq { expression, expression }
-  | element df { expression, expression }
-  | element lt { expression, expression }
-  | element gt { expression, expression }
-  | element leq { expression, expression }
-  | element geq { expression, expression }
-# ***********************************************************
-
-# V.2.5. Conditional Expressions
-
-# ***********************************************************
-conditional-operation = if-then-else-operation | switch-operation
-if-then-else-operation =
-  element ite { expression, expression, expression }
-switch-operation = element switch { case-operation*, expression }
-case-operation = element case { expression, expression }
-# ***********************************************************
-
-# V.2.6. Built-ins
-
-# ***********************************************************
-exponential = element exponential { expression, expression }
-GLM = element GLM { expression, expression, expression, expression }
-Weibull =
-  element Weibull { expression, expression, expression, expression }
-periodic-test =
-  element periodic-test {
-    expression, expression, expression, expression
-  }
-  | element periodic-test {
-      expression, expression, expression, expression, expression
-    }
-  | element periodic-test {
-      expression,
-      expression,
-      expression,
-      expression,
-      expression,
-      expression,
-      expression,
-      expression,
-      expression,
-      expression,
-      expression
-    }
-extern-function = element extern-function { name, expression* }
-# ***********************************************************
-
-# V.2.7. Random-Deviates
-
-# ***********************************************************
-uniform-deviate = element uniform-deviate { expression, expression }
-normal-deviate = element normal-deviate { expression, expression }
-lognormal-deviate =
-  element lognormal-deviate { expression, expression, expression }
-gamma-deviate = element gamma-deviate { expression, expression }
-beta-deviate = element beta-deviate { expression, expression }
-histogram = element histogram { bin+ }
-bin = element bin { expression, expression }
-# ***********************************************************
-
-# V.2.8. Test-Events
-
-# ***********************************************************
-test-initiating-event = element test-initiating-event { name }
-test-functional-event =
-  element test-functional-event {
-    name,
-    attribute state { xsd:string }
-  }
diff --git a/share/open-psa/mef.rng b/share/open-psa/mef.rng
deleted file mode 100644
index c67a6cb..0000000
--- a/share/open-psa/mef.rng
+++ /dev/null
@@ -1,1341 +0,0 @@
-<grammar xmlns="http://relaxng.org/ns/structure/1.0"
-  datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
-
-<!-- ############################################################### -->
-<!-- I. Calculation Layer -->
-<!-- ############################################################### -->
-
-  <!-- ============================================================= -->
-  <!-- I.1. Models -->
-  <!-- ============================================================= -->
-
-  <start>
-    <element name="opsa-mef">
-      <optional>
-        <ref name="name"/>
-      </optional>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <zeroOrMore>
-        <choice>
-          <ref name="event-tree-definition"/>
-          <ref name="alignment-definition"/>
-          <ref name="consequence-group-definition"/>
-          <ref name="consequence-definition"/>
-          <ref name="rule-definition"/>
-          <ref name="initiating-event-group-definition"/>
-          <ref name="initiating-event-definition"/>
-          <ref name="fault-tree-definition"/>
-          <ref name="substitution-definition"/>
-          <ref name="CCF-group-definition"/>
-          <ref name="include-directive"/>
-        </choice>
-      </zeroOrMore>
-      <optional>
-        <element name="model-data">
-          <zeroOrMore>
-            <choice>
-              <ref name="house-event-definition"/>
-              <ref name="basic-event-definition"/>
-              <ref name="parameter-definition"/>
-              <ref name="include-directive"/>
-            </choice>
-          </zeroOrMore>
-        </element>
-      </optional>
-    </element>
-  </start>
-
-  <define name="Identifier">
-    <data type="NCName">
-      <param name="pattern">[^\-.]+(-[^\-.]+)*</param>
-    </data>
-  </define>
-
-  <define name="name">
-    <attribute name="name"> <ref name="Identifier"/> </attribute>
-  </define>
-
-  <define name="reference">
-    <attribute name="name">
-      <data type="NCName">
-        <param name="pattern">([^\-.]+(-[^\-.]+)*)(\.\i[^\-.]*(-[^\-.]+)*)*</param>
-      </data>
-    </attribute>
-  </define>
-
-  <define name="label">
-    <element name="label"> <text/> </element>
-  </define>
-
-  <define name="attributes">
-    <element name="attributes">
-      <zeroOrMore>
-        <element name="attribute">
-          <ref name="name"/>
-          <attribute name="value"> <data type="string"/> </attribute>
-          <optional>
-            <attribute name="type"> <data type="string"/> </attribute>
-          </optional>
-        </element>
-      </zeroOrMore>
-    </element>
-  </define>
-
-  <define name="include-directive">
-    <element name="include">
-      <attribute name="file"> <data type="string"/> </attribute>
-    </element>
-  </define>
-
-
-  <!-- ============================================================= -->
-  <!-- I.2. Consequences, Consequence Groups -->
-  <!-- ============================================================= -->
-
-  <define name="consequence-definition">
-    <element name="define-consequence">
-      <ref name="name"/>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <element name="initiating-event">
-        <ref name="name"/>
-      </element>
-      <element name="sequence">
-        <ref name="name"/>
-      </element>
-    </element>
-  </define>
-
-  <define name="consequence-group-definition">
-    <element name="define-consequence-group">
-      <ref name="name"/>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <choice>
-        <ref name="consequence"/>
-        <ref name="consequence-group"/>
-      </choice>
-    </element>
-  </define>
-
-  <define name="consequence">
-    <element name="consequence">
-      <ref name="name"/>
-    </element>
-  </define>
-
-  <define name="consequence-group">
-    <element name="consequence-group">
-      <ref name="name"/>
-    </element>
-  </define>
-
-  <!-- ============================================================= -->
-  <!-- I.3. Missions, Phases -->
-  <!-- ============================================================= -->
-
-  <define name="alignment-definition">
-    <element name="define-alignment">
-      <ref name="name"/>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <oneOrMore>
-        <ref name="phase-definition"/>
-      </oneOrMore>
-    </element>
-  </define>
-
-  <define name="phase-definition">
-    <element name="define-phase">
-      <ref name="name"/>
-      <attribute name="time-fraction"> <data type="double"/> </attribute>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <zeroOrMore>
-        <ref name="instruction"/>
-      </zeroOrMore>
-    </element>
-  </define>
-
-
-<!-- ############################################################### -->
-<!-- II. Event Tree Layer -->
-<!-- ############################################################### -->
-
-  <!-- ============================================================= -->
-  <!-- II.1. Initiating events, Initiating event Groups -->
-  <!-- ============================================================= -->
-
-  <define name="initiating-event-definition">
-    <element name="define-initiating-event">
-      <ref name="name"/>
-      <optional>
-        <attribute name="event-tree"> <ref name="Identifier"/> </attribute>
-      </optional>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <optional>
-        <choice>
-          <ref name="collected-item"/>
-          <ref name="consequence"/>
-          <ref name="consequence-group"/>
-        </choice>
-      </optional>
-    </element>
-  </define>
-
-  <define name="initiating-event-group-definition">
-    <element name="define-initiating-event-group">
-      <ref name="name"/>
-      <optional>
-        <attribute name="event-tree"> <ref name="Identifier"/> </attribute>
-      </optional>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <oneOrMore>
-        <ref name="initiating-event"/>
-      </oneOrMore>
-    </element>
-  </define>
-
-  <define name="initiating-event">
-    <choice>
-      <element name="initiating-event">
-        <ref name="name"/>
-      </element>
-      <element name="initiating-event-group">
-        <ref name="name"/>
-      </element>
-    </choice>
-  </define>
-
-  <define name="collected-item">
-    <choice>
-      <ref name="basic-event"/>
-      <ref name="gate"/>
-      <ref name="parameter"/>
-    </choice>
-  </define>
-
-
-  <!-- ============================================================= -->
-  <!-- II.2. Event Trees -->
-  <!-- ============================================================= -->
-
-  <define name="event-tree-definition">
-    <element name="define-event-tree">
-      <ref name="name"/>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <zeroOrMore>
-        <ref name="functional-event-definition"/>
-      </zeroOrMore>
-      <zeroOrMore>
-        <ref name="sequence-definition"/>
-      </zeroOrMore>
-      <zeroOrMore>
-        <ref name="branch-definition"/>
-      </zeroOrMore>
-      <ref name="initial-state"/>
-    </element>
-  </define>
-
-  <define name="functional-event-definition">
-    <element name="define-functional-event">
-      <ref name="name"/>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-    </element>
-  </define>
-
-  <define name="sequence-definition">
-    <element name="define-sequence">
-      <ref name="name"/>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <oneOrMore>
-        <ref name="instruction"/>
-      </oneOrMore>
-    </element>
-  </define>
-
-  <define name="branch-definition">
-    <element name="define-branch">
-      <ref name="name"/>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <ref name="branch"/>
-    </element>
-  </define>
-
-  <define name="initial-state">
-    <element name="initial-state">
-      <ref name="branch"/>
-    </element>
-  </define>
-
-  <define name="branch">
-    <zeroOrMore>
-      <ref name="instruction"/>
-    </zeroOrMore>
-    <choice>
-      <ref name="fork"/>
-      <ref name="end-state"/>
-    </choice>
-  </define>
-
-  <define name="fork">
-    <element name="fork">
-      <attribute name="functional-event"> <ref name="Identifier"/> </attribute>
-      <oneOrMore>
-        <ref name="path"/>
-      </oneOrMore>
-    </element>
-  </define>
-
-  <define name="path">
-    <element name="path">
-      <attribute name="state"> <ref name="Identifier"/> </attribute>
-      <ref name="branch"/>
-    </element>
-  </define>
-
-  <define name="end-state">
-    <choice>
-      <element name="sequence">
-        <ref name="name"/>
-      </element>
-      <element name="branch">
-        <ref name="name"/>
-      </element>
-    </choice>
-  </define>
-
-  <!-- ============================================================= -->
-  <!-- II.3. Instructions, Rules -->
-  <!-- ============================================================= -->
-
-  <define name="instruction">
-    <choice>
-      <ref name="set"/>
-      <ref name="collect"/>
-      <ref name="if-then-else"/>
-      <ref name="block"/>
-      <ref name="rule"/>
-      <ref name="link"/>
-    </choice>
-  </define>
-
-  <define name="set">
-    <choice>
-      <ref name="set-gate"/>
-      <ref name="set-house-event"/>
-      <ref name="set-basic-event"/>
-      <ref name="set-parameter"/>
-    </choice>
-  </define>
-
-  <define name="set-gate">
-    <element name="set-gate">
-      <ref name="name"/>
-      <optional>
-        <attribute name="direction">
-          <ref name="direction"/>
-        </attribute>
-      </optional>
-      <ref name="formula"/>
-    </element>
-  </define>
-
-  <define name="set-house-event">
-    <element name="set-house-event">
-      <ref name="name"/>
-      <optional>
-        <attribute name="direction">
-          <ref name="direction"/>
-        </attribute>
-      </optional>
-      <ref name="Boolean-constant"/>
-    </element>
-  </define>
-
-  <define name="set-basic-event">
-    <element name="set-basic-event">
-      <ref name="name"/>
-      <optional>
-        <attribute name="direction">
-          <ref name="direction"/>
-        </attribute>
-      </optional>
-      <ref name="expression"/>
-    </element>
-  </define>
-
-  <define name="set-parameter">
-    <element name="set-parameter">
-      <ref name="name"/>
-      <optional>
-        <attribute name="direction">
-          <ref name="direction"/>
-        </attribute>
-      </optional>
-      <ref name="expression"/>
-    </element>
-  </define>
-
-  <define name="direction">
-    <choice>
-      <value>forward</value>
-      <value>backward</value>
-      <value>both</value>
-    </choice>
-  </define>
-
-  <define name="if-then-else">
-    <element name="if">
-      <ref name="expression"/>
-      <ref name="instruction"/>
-      <optional>
-        <ref name="instruction"/>
-      </optional>
-    </element>
-  </define>
-
-  <define name="collect">
-    <choice>
-      <ref name="collect-formula"/>
-      <ref name="collect-expression"/>
-    </choice>
-  </define>
-
-  <define name="collect-formula">
-    <element name="collect-formula">
-      <ref name="formula"/>
-    </element>
-  </define>
-
-  <define name="collect-expression">
-    <element name="collect-expression">
-      <ref name="expression"/>
-    </element>
-  </define>
-
-  <define name="block">
-    <element name="block">
-      <zeroOrMore>
-        <ref name="instruction"/>
-      </zeroOrMore>
-    </element>
-  </define>
-
-  <define name="rule">
-    <element name="rule">
-      <ref name="name"/>
-    </element>
-  </define>
-
-  <define name="link">
-    <element name="event-tree">
-      <ref name="name"/>
-    </element>
-  </define>
-
-  <define name="rule-definition">
-    <element name="define-rule">
-      <ref name="name"/>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <oneOrMore>
-        <ref name="instruction"/>
-      </oneOrMore>
-    </element>
-  </define>
-
-
-<!-- ############################################################### -->
-<!-- III. Meta-Logical Layer -->
-<!-- ############################################################### -->
-
-  <!-- ============================================================= -->
-  <!-- III.1. CCF-Groups -->
-  <!-- ============================================================= -->
-
-  <define name="CCF-group-definition">
-    <element name="define-CCF-group">
-      <ref name="name"/>
-      <attribute name="model">
-        <ref name="CCF-model"/>
-      </attribute>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <ref name="members"/>
-      <ref name="distribution"/>
-      <ref name="factors"/>
-    </element>
-  </define>
-
-  <define name="members">
-    <element name="members">
-      <oneOrMore>
-        <ref name="basic-event"/>
-      </oneOrMore>
-    </element>
-  </define>
-
-  <define name="factors">
-    <choice>
-      <element name="factors">
-        <oneOrMore>
-          <ref name="factor"/>
-        </oneOrMore>
-      </element>
-      <ref name="factor"/>
-    </choice>
-  </define>
-
-  <define name="factor">
-    <element name="factor">
-      <optional>
-        <attribute name="level"> <data type="nonNegativeInteger"/> </attribute>
-      </optional>
-      <ref name="expression"/>
-    </element>
-  </define>
-
-  <define name="distribution">
-    <element name="distribution">
-      <ref name="expression"/>
-    </element>
-  </define>
-
-  <define name="CCF-model">
-    <choice>
-      <value>beta-factor</value>
-      <value>MGL</value>
-      <value>alpha-factor</value>
-      <value>phi-factor</value>
-    </choice>
-  </define>
-
-  <!-- ============================================================= -->
-  <!-- III.2. Substitutions -->
-  <!-- ============================================================= -->
-
-  <define name="substitution-definition">
-    <element name="define-substitution">
-      <optional>
-        <ref name="name"/>
-      </optional>
-      <optional>
-        <attribute name="type"> <data type="string"/> </attribute>
-      </optional>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <element name="hypothesis">
-        <ref name="formula"/>
-      </element>
-      <optional>
-        <element name="source">
-          <oneOrMore>
-            <ref name="basic-event"/>
-          </oneOrMore>
-        </element>
-      </optional>
-      <element name="target">
-        <choice>
-          <oneOrMore>
-            <ref name="basic-event"/>
-          </oneOrMore>
-          <ref name="Boolean-constant"/>
-        </choice>
-      </element>
-    </element>
-  </define>
-
-
-<!-- ############################################################### -->
-<!-- IV. Fault Tree Layer -->
-<!-- ############################################################### -->
-
-  <!-- ============================================================= -->
-  <!-- IV.1. Definitions of Fault Trees & Components -->
-  <!-- ============================================================= -->
-
-  <define name="fault-tree-definition">
-    <element name="define-fault-tree">
-      <ref name="name"/>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <zeroOrMore>
-        <choice>
-          <ref name="substitution-definition"/>
-          <ref name="CCF-group-definition"/>
-          <ref name="event-definition"/>
-          <ref name="component-definition"/>
-          <ref name="parameter-definition"/>
-          <ref name="include-directive"/>
-        </choice>
-      </zeroOrMore>
-    </element>
-  </define>
-
-  <define name="component-definition">
-    <element name="define-component">
-      <ref name="name"/>
-      <optional>
-        <ref name="role"/>
-      </optional>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <zeroOrMore>
-        <choice>
-          <ref name="substitution-definition"/>
-          <ref name="CCF-group-definition"/>
-          <ref name="event-definition"/>
-          <ref name="component-definition"/>
-          <ref name="parameter-definition"/>
-          <ref name="include-directive"/>
-        </choice>
-      </zeroOrMore>
-    </element>
-  </define>
-
-  <define name="role">
-    <attribute name="role">
-      <choice>
-        <value>private</value>
-        <value>public</value>
-      </choice>
-    </attribute>
-  </define>
-
-  <define name="event-definition">
-    <choice>
-      <ref name="gate-definition"/>
-      <ref name="house-event-definition"/>
-      <ref name="basic-event-definition"/>
-    </choice>
-  </define>
-
-  <!-- ============================================================= -->
-  <!-- IV.2. Definitions of Gates, House Events & Basic Events -->
-  <!-- ============================================================= -->
-
-  <define name="gate-definition">
-    <element name="define-gate">
-      <ref name="name"/>
-      <optional>
-        <ref name="role"/>
-      </optional>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <ref name="formula"/>
-    </element>
-  </define>
-
-  <define name="house-event-definition">
-    <element name="define-house-event">
-      <ref name="name"/>
-      <optional>
-        <ref name="role"/>
-      </optional>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <optional>
-        <ref name="Boolean-constant"/>
-      </optional>
-    </element>
-  </define>
-
-  <define name="basic-event-definition">
-    <element name="define-basic-event">
-      <ref name="name"/>
-      <optional>
-        <ref name="role"/>
-      </optional>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <optional>
-        <ref name="expression"/>
-      </optional>
-    </element>
-  </define>
-
-
-  <!-- ============================================================= -->
-  <!-- IV.3. Formulae -->
-  <!-- ============================================================= -->
-
-  <define name="formula">
-    <choice>
-      <ref name="event"/>
-      <ref name="Boolean-constant"/>
-      <element name="and">
-        <oneOrMore>
-          <ref name="formula"/>
-        </oneOrMore>
-      </element>
-      <element name="or">
-        <oneOrMore>
-          <ref name="formula"/>
-        </oneOrMore>
-      </element>
-      <element name="not">
-        <ref name="formula"/>
-      </element>
-      <element name="xor">
-        <oneOrMore>
-          <ref name="formula"/>
-        </oneOrMore>
-      </element>
-      <element name="iff">
-        <oneOrMore>
-          <ref name="formula"/>
-        </oneOrMore>
-      </element>
-      <element name="nand">
-        <oneOrMore>
-          <ref name="formula"/>
-        </oneOrMore>
-      </element>
-      <element name="nor">
-        <oneOrMore>
-          <ref name="formula"/>
-        </oneOrMore>
-      </element>
-      <element name="atleast">
-        <attribute name="min"> <data type="nonNegativeInteger"/> </attribute>
-        <oneOrMore>
-          <ref name="formula"/>
-        </oneOrMore>
-      </element>
-      <element name="cardinality">
-        <attribute name="min"> <data type="nonNegativeInteger"/> </attribute>
-        <attribute name="max"> <data type="nonNegativeInteger"/> </attribute>
-        <oneOrMore>
-          <ref name="formula"/>
-        </oneOrMore>
-      </element>
-      <element name="imply">
-        <ref name="formula"/>
-        <ref name="formula"/>
-      </element>
-    </choice>
-  </define>
-
-  <define name="event">
-    <choice>
-      <element name="event">
-        <ref name="reference"/>
-        <optional>
-          <attribute name="type">
-            <ref name="event-type"/>
-          </attribute>
-        </optional>
-      </element>
-      <ref name="gate"/>
-      <ref name="house-event"/>
-      <ref name="basic-event"/>
-    </choice>
-  </define>
-
-  <define name="event-type">
-    <choice>
-      <value>gate</value>
-      <value>basic-event</value>
-      <value>house-event</value>
-    </choice>
-  </define>
-
-  <define name="gate">
-    <element name="gate">
-      <ref name="reference"/>
-    </element>
-  </define>
-
-  <define name="house-event">
-    <element name="house-event">
-      <ref name="reference"/>
-    </element>
-  </define>
-
-  <define name="basic-event">
-    <element name="basic-event">
-      <ref name="reference"/>
-    </element>
-  </define>
-
-  <define name="Boolean-constant">
-    <element name="constant">
-      <attribute name="value">
-        <ref name="Boolean-value"/>
-      </attribute>
-    </element>
-  </define>
-
-  <define name="Boolean-value">
-    <choice>
-      <value>true</value>
-      <value>false</value>
-    </choice>
-  </define>
-
-
-<!-- ############################################################### -->
-<!-- V. Stochastic Layer -->
-<!-- ############################################################### -->
-
-  <!-- ============================================================= -->
-  <!-- V.1. Definition of Parameters -->
-  <!-- ============================================================= -->
-
-  <define name="parameter-definition">
-    <element name="define-parameter">
-      <ref name="name"/>
-      <optional>
-        <ref name="role"/>
-      </optional>
-      <optional>
-        <attribute name="unit">
-          <ref name="units"/>
-        </attribute>
-      </optional>
-      <optional>
-        <ref name="label"/>
-      </optional>
-      <optional>
-        <ref name="attributes"/>
-      </optional>
-      <ref name="expression"/>
-    </element>
-  </define>
-
-  <define name="units">
-    <choice>
-      <value>bool</value>
-      <value>int</value>
-      <value>float</value>
-      <value>hours</value>
-      <value>hours-1</value>
-      <value>years</value>
-      <value>years-1</value>
-      <value>fit</value>
-      <value>demands</value>
-    </choice>
-  </define>
-
-  <!-- ============================================================= -->
-  <!-- V.2. Expressions -->
-  <!-- ============================================================= -->
-
-    <!-- *********************************************************** -->
-    <!-- V.2.1. Entities -->
-    <!-- *********************************************************** -->
-
-  <define name="expression">
-    <choice>
-      <ref name="constant"/>
-      <ref name="parameter"/>
-      <ref name="operation"/>
-      <ref name="built-in"/>
-      <ref name="random-deviate"/>
-      <ref name="test-event"/>
-    </choice>
-  </define>
-
-  <define name="constant">
-    <choice>
-      <ref name="bool"/>
-      <ref name="int"/>
-      <ref name="float"/>
-    </choice>
-  </define>
-
-  <define name="parameter">
-    <choice>
-      <element name="parameter">
-        <ref name="reference"/>
-        <optional>
-          <attribute name="unit">
-            <ref name="units"/>
-          </attribute>
-        </optional>
-      </element>
-      <element name="system-mission-time">
-        <optional>
-          <attribute name="unit">
-            <ref name="units"/>
-          </attribute>
-        </optional>
-      </element>
-    </choice>
-  </define>
-
-  <define name="operation">
-    <choice>
-      <ref name="numerical-operation"/>
-      <ref name="Boolean-operation"/>
-      <ref name="conditional-operation"/>
-    </choice>
-  </define>
-
-  <define name="built-in">
-    <choice>
-      <ref name="exponential"/>
-      <ref name="GLM"/>
-      <ref name="Weibull"/>
-      <ref name="periodic-test"/>
-      <ref name="extern-function"/>
-    </choice>
-  </define>
-
-  <define name="random-deviate">
-    <choice>
-      <ref name="uniform-deviate"/>
-      <ref name="normal-deviate"/>
-      <ref name="lognormal-deviate"/>
-      <ref name="gamma-deviate"/>
-      <ref name="beta-deviate"/>
-      <ref name="histogram"/>
-    </choice>
-  </define>
-
-  <define name="test-event">
-    <choice>
-      <ref name="test-initiating-event"/>
-      <ref name="test-functional-event"/>
-    </choice>
-  </define>
-
-    <!-- *********************************************************** -->
-    <!-- V.2.2. Constants, Parameters -->
-    <!-- *********************************************************** -->
-
-    <define name="bool">
-      <element name="bool">
-        <attribute name="value">
-          <ref name="Boolean-value"/>
-        </attribute>
-      </element>
-    </define>
-
-    <define name="int">
-      <element name="int">
-        <attribute name="value">
-          <data type="integer"/>
-        </attribute>
-      </element>
-    </define>
-
-    <define name="float">
-      <element name="float">
-        <attribute name="value">
-          <data type="double"/>
-        </attribute>
-      </element>
-    </define>
-
-    <!-- *********************************************************** -->
-    <!-- V.2.3. Numerical Expressions -->
-    <!-- *********************************************************** -->
-
-  <define name="numerical-operation">
-    <choice>
-      <element name="neg">
-        <ref name="expression"/>
-      </element>
-      <element name="add">
-        <oneOrMore>
-          <ref name="expression"/>
-        </oneOrMore>
-      </element>
-      <element name="sub">
-        <oneOrMore>
-          <ref name="expression"/>
-        </oneOrMore>
-      </element>
-      <element name="mul">
-        <oneOrMore>
-          <ref name="expression"/>
-        </oneOrMore>
-      </element>
-      <element name="div">
-        <oneOrMore>
-          <ref name="expression"/>
-        </oneOrMore>
-      </element>
-      <element name="pi"> <empty/> </element>
-      <element name="abs">
-        <ref name="expression"/>
-      </element>
-      <element name="acos">
-        <ref name="expression"/>
-      </element>
-      <element name="asin">
-        <ref name="expression"/>
-      </element>
-      <element name="atan">
-        <ref name="expression"/>
-      </element>
-      <element name="cos">
-        <ref name="expression"/>
-      </element>
-      <element name="cosh">
-        <ref name="expression"/>
-      </element>
-      <element name="exp">
-        <ref name="expression"/>
-      </element>
-      <element name="log">
-        <ref name="expression"/>
-      </element>
-      <element name="log10">
-        <ref name="expression"/>
-      </element>
-      <element name="mod">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-      <element name="pow">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-      <element name="sin">
-        <ref name="expression"/>
-      </element>
-      <element name="sinh">
-        <ref name="expression"/>
-      </element>
-      <element name="tan">
-        <ref name="expression"/>
-      </element>
-      <element name="tanh">
-        <ref name="expression"/>
-      </element>
-      <element name="sqrt">
-        <ref name="expression"/>
-      </element>
-      <element name="ceil">
-        <ref name="expression"/>
-      </element>
-      <element name="floor">
-        <ref name="expression"/>
-      </element>
-      <element name="min">
-        <oneOrMore>
-          <ref name="expression"/>
-        </oneOrMore>
-      </element>
-      <element name="max">
-        <oneOrMore>
-          <ref name="expression"/>
-        </oneOrMore>
-      </element>
-      <element name="mean">
-        <oneOrMore>
-          <ref name="expression"/>
-        </oneOrMore>
-      </element>
-    </choice>
-  </define>
-
-    <!-- *********************************************************** -->
-    <!-- V.2.4. Boolean Expressions -->
-    <!-- *********************************************************** -->
-
-  <define name="Boolean-operation">
-    <choice>
-      <element name="not">
-        <ref name="expression"/>
-      </element>
-      <element name="and">
-        <oneOrMore>
-          <ref name="expression"/>
-        </oneOrMore>
-      </element>
-      <element name="or">
-        <oneOrMore>
-          <ref name="expression"/>
-        </oneOrMore>
-      </element>
-      <element name="eq">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-      <element name="df">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-      <element name="lt">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-      <element name="gt">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-      <element name="leq">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-      <element name="geq">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-    </choice>
-  </define>
-
-    <!-- *********************************************************** -->
-    <!-- V.2.5. Conditional Expressions -->
-    <!-- *********************************************************** -->
-
-  <define name="conditional-operation">
-    <choice>
-      <ref name="if-then-else-operation"/>
-      <ref name="switch-operation"/>
-    </choice>
-  </define>
-
-  <define name="if-then-else-operation">
-    <element name="ite">
-      <ref name="expression"/>
-      <ref name="expression"/>
-      <ref name="expression"/>
-    </element>
-  </define>
-
-  <define name="switch-operation">
-    <element name="switch">
-      <zeroOrMore>
-        <ref name="case-operation"/>
-      </zeroOrMore>
-      <ref name="expression"/>
-    </element>
-  </define>
-
-  <define name="case-operation">
-    <element name="case">
-      <ref name="expression"/>
-      <ref name="expression"/>
-    </element>
-  </define>
-
-    <!-- *********************************************************** -->
-    <!-- V.2.6. Built-ins -->
-    <!-- *********************************************************** -->
-
-    <define name="exponential">
-      <element name="exponential">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-    </define>
-
-    <define name="GLM">
-      <element name="GLM">
-        <ref name="expression"/>
-        <ref name="expression"/>
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-    </define>
-
-    <define name="Weibull">
-      <element name="Weibull">
-        <ref name="expression"/>
-        <ref name="expression"/>
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-    </define>
-
-    <define name="periodic-test">
-      <choice>
-        <element name="periodic-test">
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-        </element>
-        <element name="periodic-test">
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-        </element>
-        <element name="periodic-test">
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-          <ref name="expression"/>
-        </element>
-      </choice>
-    </define>
-
-    <define name="extern-function">
-      <element name="extern-function">
-        <ref name="name"/>
-        <zeroOrMore>
-          <ref name="expression"/>
-        </zeroOrMore>
-      </element>
-    </define>
-
-    <!-- *********************************************************** -->
-    <!-- V.2.7. Random-Deviates -->
-    <!-- *********************************************************** -->
-
-    <define name="uniform-deviate">
-      <element name="uniform-deviate">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-    </define>
-
-    <define name="normal-deviate">
-      <element name="normal-deviate">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-    </define>
-
-    <define name="lognormal-deviate">
-      <element name="lognormal-deviate">
-        <ref name="expression"/>
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-    </define>
-
-    <define name="gamma-deviate">
-      <element name="gamma-deviate">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-    </define>
-
-    <define name="beta-deviate">
-      <element name="beta-deviate">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-    </define>
-
-    <define name="histogram">
-      <element name="histogram">
-        <oneOrMore>
-          <ref name="bin"/>
-        </oneOrMore>
-      </element>
-    </define>
-
-    <define name="bin">
-      <element name="bin">
-        <ref name="expression"/>
-        <ref name="expression"/>
-      </element>
-    </define>
-
-    <!-- *********************************************************** -->
-    <!-- V.2.8. Test-Events -->
-    <!-- *********************************************************** -->
-
-    <define name="test-initiating-event">
-      <element name="test-initiating-event">
-        <ref name="name"/>
-      </element>
-    </define>
-
-    <define name="test-functional-event">
-      <element name="test-functional-event">
-        <ref name="name"/>
-        <attribute name="state"> <data type="string"/> </attribute>
-      </element>
-    </define>
-
-</grammar>
diff --git a/share/open-psa/stat_measures.bnf b/share/open-psa/stat_measures.bnf
deleted file mode 100644
index 90a79ed..0000000
--- a/share/open-psa/stat_measures.bnf
+++ /dev/null
@@ -1,26 +0,0 @@
-measure ::=
-  <measure
-    [ name="identifier" ]
-    [ description="text" ]
-  >
-    [ <mean value="float" > ]
-    [ <standard-deviation value="float" > ]
-    [ <confidence-range
-        percentage="float"
-        lower-bound="float"
-        upper-bound="float" > ]
-    [ <error-factor percentage="float" value="float" > ]
-    [ quantiles ]
-  </measure>
-
-quantiles ::=
-  <quantiles number="integer" >
-    quantile+
-  </quantiles>
-
-quantile ::=
-  <quantile number="integer"
-    [ mean="float" ]
-    [ lower-bound="float" ]
-    [ upper-bound="float" ]
-  />
diff --git a/share/report_layer.rng b/share/report_layer.rng
index f8fdedf..51c7e11 100644
--- a/share/report_layer.rng
+++ b/share/report_layer.rng
@@ -12,6 +12,13 @@
     </element>
   </start>
 
+  <define name="probability-data">  <!-- [0.0, 1.0] values for probability -->
+    <data type="double">
+      <param name="minInclusive">0</param>
+      <param name="maxInclusive">1</param>
+    </data>
+  </define>
+
 <!-- ############################################################### -->
 <!-- I. Information Layer -->
 <!-- ############################################################### -->
@@ -20,7 +27,7 @@
     <element name="information">
       <optional>
         <element name="software">
-          <attribute name="name"> <data type="NCName"/> </attribute>
+          <attribute name="name"> <data type="string"/> </attribute>
           <attribute name="version"> <data type="string"/> </attribute>
           <optional>
             <attribute name="contacts"> <text/> </attribute>
@@ -28,7 +35,7 @@
         </element>
       </optional>
       <optional>
-        <element name="time"> <text/> </element>
+        <element name="time"> <data type="string"/> </element>
       </optional>
       <optional>
         <element name="performance">
@@ -85,7 +92,7 @@
                   </element>
                 </optional>
                 <optional>
-                  <element name="cut-off"> <data type="double"/> </element>
+                  <element name="cut-off"> <ref name="probability-data"/> </element>
                 </optional>
                 <optional>
                   <element name="number-of-sums">
@@ -211,7 +218,7 @@
         </attribute>
       </optional>
       <optional>
-        <attribute name="probability"> <data type="double"/> </attribute>
+        <attribute name="probability"> <ref name="probability-data"/> </attribute>
       </optional>
       <optional>
         <element name="warning"> <text/> </element>
@@ -230,10 +237,10 @@
         </attribute>
       </optional>
       <optional>
-        <attribute name="probability"> <data type="double"/> </attribute>
+        <attribute name="probability"> <ref name="probability-data"/> </attribute>
       </optional>
       <optional>
-        <attribute name="contribution"> <data type="double"/> </attribute>
+        <attribute name="contribution"> <ref name="probability-data"/> </attribute>
       </optional>
       <zeroOrMore>
         <ref name="literal"/>
@@ -287,25 +294,39 @@
       </optional>
       <optional>
         <element name="mean">
-          <attribute name="value"> <data type="double"/> </attribute>
+          <attribute name="value"> <ref name="probability-data"/> </attribute>
         </element>
       </optional>
       <optional>
         <element name="standard-deviation">
-          <attribute name="value"> <data type="double"/> </attribute>
+          <attribute name="value"> <ref name="probability-data"/> </attribute>
         </element>
       </optional>
       <optional>
         <element name="confidence-range">
-          <attribute name="percentage"> <data type="double"/> </attribute>
-          <attribute name="lower-bound"> <data type="double"/> </attribute>
-          <attribute name="upper-bound"> <data type="double"/> </attribute>
+          <attribute name="percentage">
+            <data type="double">
+              <param name="minExclusive">0</param>
+              <param name="maxExclusive">100</param>
+            </data>
+          </attribute>
+          <attribute name="lower-bound"> <ref name="probability-data"/> </attribute>
+          <attribute name="upper-bound"> <ref name="probability-data"/> </attribute>
         </element>
       </optional>
       <optional>
         <element name="error-factor">
-          <attribute name="percentage"> <data type="double"/> </attribute>
-          <attribute name="value"> <data type="double"/> </attribute>
+          <attribute name="percentage">
+            <data type="double">
+              <param name="minExclusive">0</param>
+              <param name="maxExclusive">100</param>
+            </data>
+          </attribute>
+          <attribute name="value">
+            <data type="double">
+              <param name="minExclusive">0</param>
+            </data>
+          </attribute>
         </element>
       </optional>
       <optional>
@@ -328,16 +349,7 @@
 
   <define name="quantile">
     <element name="quantile">
-      <attribute name="number"> <data type="nonNegativeInteger"/> </attribute>
-      <optional>
-        <attribute name="value"> <data type="double"/> </attribute>
-      </optional>
-      <optional>
-        <attribute name="lower-bound"> <data type="double"/> </attribute>
-      </optional>
-      <optional>
-        <attribute name="upper-bound"> <data type="double"/> </attribute>
-      </optional>
+      <ref name="bin-data"/>
     </element>
   </define>
 
@@ -352,19 +364,23 @@
 
   <define name="bin">
     <element name="bin">
-      <attribute name="number"> <data type="nonNegativeInteger"/> </attribute>
-      <optional>
-        <attribute name="value"> <data type="double"/> </attribute>
-      </optional>
-      <optional>
-        <attribute name="lower-bound"> <data type="double"/> </attribute>
-      </optional>
-      <optional>
-        <attribute name="upper-bound"> <data type="double"/> </attribute>
-      </optional>
+      <ref name="bin-data"/>
     </element>
   </define>
 
+  <define name="bin-data">
+    <attribute name="number"> <data type="nonNegativeInteger"/> </attribute>
+    <optional>
+      <attribute name="value"> <data type="double"/> </attribute>
+    </optional>
+    <optional>
+      <attribute name="lower-bound"> <data type="double"/> </attribute>
+    </optional>
+    <optional>
+      <attribute name="upper-bound"> <data type="double"/> </attribute>
+    </optional>
+  </define>
+
   <!-- ============================================================= -->
   <!-- II.3. Curves -->
   <!-- ============================================================= -->
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5c6000c..0b3f6bd 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -34,6 +34,11 @@ set(SCRAM_CORE_SRC
   "${CMAKE_CURRENT_SOURCE_DIR}/cycle.cc"
   "${CMAKE_CURRENT_SOURCE_DIR}/element.cc"
   "${CMAKE_CURRENT_SOURCE_DIR}/expression.cc"
+  "${CMAKE_CURRENT_SOURCE_DIR}/parameter.cc"
+  "${CMAKE_CURRENT_SOURCE_DIR}/expression/constant.cc"
+  "${CMAKE_CURRENT_SOURCE_DIR}/expression/arithmetic.cc"
+  "${CMAKE_CURRENT_SOURCE_DIR}/expression/exponential.cc"
+  "${CMAKE_CURRENT_SOURCE_DIR}/expression/random_deviate.cc"
   "${CMAKE_CURRENT_SOURCE_DIR}/event.cc"
   "${CMAKE_CURRENT_SOURCE_DIR}/ccf_group.cc"
   "${CMAKE_CURRENT_SOURCE_DIR}/fault_tree.cc"
@@ -54,30 +59,31 @@ set(SCRAM_CORE_SRC
   )
 add_library(scramcore ${SCRAM_CORE_SRC})
 
-set_target_properties(scramcore
-  PROPERTIES
-  INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib"
-  INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"
-  LINK_FLAGS "${LIB_LINK_FLAGS}"
-  )
-
-target_link_libraries(scramcore ${LIBS})
-
-if(WIN32)
-  install(
-    TARGETS scramcore
-    RUNTIME DESTINATION bin COMPONENT scram
-    LIBRARY DESTINATION lib COMPONENT scram
-    ARCHIVE DESTINATION lib COMPONENT scram
-    )
-else()
-  install(
-    TARGETS scramcore
-    DESTINATION lib
-    COMPONENT scram
+if(INSTALL_LIBS)
+  set_target_properties(scramcore
+    PROPERTIES
+    INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib"
+    INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"
+    LINK_FLAGS "${LIB_LINK_FLAGS}"
     )
+  if(WIN32)
+    install(
+      TARGETS scramcore
+      RUNTIME DESTINATION bin COMPONENT scram
+      LIBRARY DESTINATION lib COMPONENT scram
+      ARCHIVE DESTINATION lib COMPONENT scram
+      )
+  else()
+    install(
+      TARGETS scramcore
+      DESTINATION lib
+      COMPONENT scram
+      )
+  endif()
 endif()
 
+target_link_libraries(scramcore ${LIBS})
+
 add_executable(scram scram.cc)
 target_link_libraries(scram scramcore ${Boost_LIBRARIES})
 
diff --git a/src/bdd.cc b/src/bdd.cc
index fffce5e..8a961a9 100644
--- a/src/bdd.cc
+++ b/src/bdd.cc
@@ -23,7 +23,6 @@
 #include <boost/multiprecision/miller_rabin.hpp>
 #include <boost/range/algorithm.hpp>
 
-#include "event.h"
 #include "ext.h"
 #include "logger.h"
 #include "zbdd.h"
diff --git a/src/bdd.h b/src/bdd.h
index 33458af..d118d8f 100644
--- a/src/bdd.h
+++ b/src/bdd.h
@@ -40,19 +40,15 @@
 namespace scram {
 namespace core {
 
-/// Control flags and pointers for communication
-/// between BDD vertex pointers and BDD tables.
-struct ControlBlock {
-  void* vertex;  ///< The manager of the control block.
-  int weak_count;  ///< Pointers in tables.
-};
-
 /// The default management of BDD vertices.
 ///
 /// @tparam T  The type of the main functional BDD vertex.
 template <class T>
 using IntrusivePtr = boost::intrusive_ptr<T>;
 
+template <class T>
+class Vertex;  // Manager of its own entry in the unique table.
+
 /// A weak pointer to store in BDD unique tables.
 /// This weak pointer is unique pointer as well
 /// because vertices should not be easily shared among multiple BDDs.
@@ -60,17 +56,20 @@ using IntrusivePtr = boost::intrusive_ptr<T>;
 /// @tparam T  The type of the main functional BDD vertex.
 template <class T>
 class WeakIntrusivePtr final : private boost::noncopyable {
+  friend class Vertex<T>;  // Communicates the destruction of the vertex.
+
  public:
   /// Default constructor is to allow initialization in tables.
-  WeakIntrusivePtr() noexcept : control_block_(nullptr) {}
+  WeakIntrusivePtr() noexcept : vertex_(nullptr) {}
 
   /// Constructs from the shared pointer.
   /// However, there is no weak-to-shared constructor.
   ///
   /// @param[in] ptr  Fully initialized intrusive pointer.
   explicit WeakIntrusivePtr(const IntrusivePtr<T>& ptr) noexcept
-      : control_block_(get_control_block(ptr.get())) {
-    control_block_->weak_count++;
+      : vertex_(ptr.get()) {
+    assert(vertex_->table_ptr_ == nullptr && "Non-unique table pointers.");
+    vertex_->table_ptr_ = this;
   }
 
   /// Copy assignment from shared pointers
@@ -85,35 +84,25 @@ class WeakIntrusivePtr final : private boost::noncopyable {
     return *this;
   }
 
-  /// Decrements weak count in the control block.
-  /// If this is the last pointer and vertex is gone,
-  /// the control block is deleted.
+  /// Communicates the pointer destruction to the vertex.
   ~WeakIntrusivePtr() noexcept {
-    if (control_block_) {
-      if (--control_block_->weak_count == 0 &&
-          control_block_->vertex == nullptr) {
-        delete control_block_;
-      }
-    }
+    if (vertex_)
+      vertex_->table_ptr_ = nullptr;
   }
 
   /// @returns true if the managed vertex is deleted or not initialized.
-  bool expired() const { return !control_block_ || !control_block_->vertex; }
+  bool expired() const { return !vertex_; }
 
   /// @returns The intrusive pointer of the vertex.
-  ///
-  /// @warning Hard failure for uninitialized pointers.
-  IntrusivePtr<T> lock() const {
-    return IntrusivePtr<T>(static_cast<T*>(control_block_->vertex));
-  }
+  ///          nullptr if the vertex is deleted or not initialized.
+  IntrusivePtr<T> lock() const { return IntrusivePtr<T>(vertex_); }
 
   /// @returns The raw pointer to the vertex.
-  ///
-  /// @warning Hard failure for uninitialized pointers.
-  T* get() const { return static_cast<T*>(control_block_->vertex); }
+  ///          nullptr if the vertex is deleted or not initialized.
+  T* get() const { return vertex_; }
 
  private:
-  ControlBlock* control_block_;  ///< To receive information from vertices.
+  T* vertex_;  ///< A communication pointer with the vertex.
 };
 
 template <class T>
@@ -130,12 +119,7 @@ class Terminal;  // Forward declaration for Vertex to manage.
 /// @pre Vertices are not shared among separate BDD instances.
 template <class T>
 class Vertex : private boost::noncopyable {
-  /// @param[in] ptr  Vertex pointer managed by intrusive pointers.
-  ///
-  /// @returns The control block of intrusive counting for tables.
-  friend ControlBlock* get_control_block(Vertex<T>* ptr) noexcept {
-    return ptr->control_block_;
-  }
+  friend class WeakIntrusivePtr<T>;  // Mutual friendship to manage table entry.
 
   /// Increases the reference count for new intrusive pointers.
   ///
@@ -165,7 +149,7 @@ class Vertex : private boost::noncopyable {
   explicit Vertex(int id)
       : id_(id),
         use_count_(0),
-        control_block_(new ControlBlock{this}) {}
+        table_ptr_(nullptr) {}
 
   /// @returns Identifier of the BDD graph rooted by this vertex.
   int id() const { return id_; }
@@ -183,20 +167,18 @@ class Vertex : private boost::noncopyable {
   }
 
  protected:
-  /// Communicates the destruction via the control block
-  /// if there's anyone left to care.
+  /// Communicates the destruction
+  /// via the pointer to the unique table entry
+  /// if there's any.
   ~Vertex() noexcept {
-    if (control_block_->weak_count == 0) {
-      delete control_block_;
-    } else {
-      control_block_->vertex = nullptr;
-    }
+    if (table_ptr_)
+      table_ptr_->vertex_ = nullptr;
   }
 
  private:
   int id_;  ///< Unique identifier of the BDD graph with this vertex.
   int use_count_;  ///< Reference count for the intrusive pointer.
-  ControlBlock* control_block_;  ///< Communication channel for pointers.
+  WeakIntrusivePtr<T>* table_ptr_;  ///< Entry in the unique table.
 };
 
 /// Representation of terminal vertices in BDD graphs.
diff --git a/src/boolean_graph.cc b/src/boolean_graph.cc
index 23f95d1..9cdc3e5 100644
--- a/src/boolean_graph.cc
+++ b/src/boolean_graph.cc
@@ -24,11 +24,14 @@
 
 #include "boolean_graph.h"
 
+#include <iostream>
 #include <string>
+#include <unordered_set>
 
 #include <boost/math/special_functions/sign.hpp>
 #include <boost/range/algorithm.hpp>
 
+#include "event.h"
 #include "logger.h"
 
 namespace scram {
@@ -837,7 +840,7 @@ std::ostream& operator<<(std::ostream& os, const VariablePtr& variable) {
 
 namespace {
 
-/// Gate formula signature for printing in the shorthand format.
+/// Gate formula signature for printing in the Aralia format.
 struct FormulaSig {
   std::string begin;  ///< Beginning of the formula string.
   std::string op;  ///< Operator between the formula arguments.
diff --git a/src/boolean_graph.h b/src/boolean_graph.h
index a59f04a..ecadb4f 100644
--- a/src/boolean_graph.h
+++ b/src/boolean_graph.h
@@ -30,34 +30,37 @@
 #ifndef SCRAM_SRC_BOOLEAN_GRAPH_H_
 #define SCRAM_SRC_BOOLEAN_GRAPH_H_
 
-#include <cassert>
 #include <cstdint>
 
 #include <algorithm>
-#include <array>
-#include <iostream>
+#include <iosfwd>
 #include <memory>
 #include <unordered_map>
-#include <unordered_set>
 #include <utility>
 #include <vector>
 
 #include <boost/container/flat_set.hpp>
-#include <boost/functional/hash.hpp>
 #include <boost/noncopyable.hpp>
 
-#include "event.h"
 #include "ext.h"
 #include "linear_map.h"
 
 namespace scram {
+
+namespace mef {  // Declarations to decouple from the initialization code.
+class Gate;
+class BasicEvent;
+class HouseEvent;
+class Formula;
+}  // namespace mef
+
 namespace core {
 
-class Gate;  // Indexed gate parent of nodes.
+class Gate;  // An indexed gate parent of nodes.
 using GatePtr = std::shared_ptr<Gate>;  ///< Shared gates in the graph.
-using GateWeakPtr = std::weak_ptr<Gate>;  ///< Acyclic ptr to parent gates.
+using GateWeakPtr = std::weak_ptr<Gate>;  ///< An acyclic ptr to parent gates.
 
-/// Manager of information about parents.
+/// A manager of information about parents.
 /// Only gates can manipulate the data.
 class NodeParentManager : private boost::noncopyable {
   friend class Gate;  ///< The main manipulator of parent information.
@@ -65,10 +68,10 @@ class NodeParentManager : private boost::noncopyable {
  public:
   using Parent = std::pair<int, GateWeakPtr>;  ///< Parent index and ptr.
 
-  /// Map of parent gate positive indices and weak pointers to them.
+  /// A map type of parent gate positive indices and weak pointers to them.
   using ParentMap = ext::linear_map<int, GateWeakPtr, ext::MoveEraser>;
 
-  /// @returns Parents of a node.
+  /// @returns The parents of a node.
   const ParentMap& parents() const { return parents_; }
 
  protected:
@@ -290,7 +293,7 @@ enum State : std::uint8_t {
   kUnityState  ///< The set is unity. This set guarantees failure.
 };
 
-/// Indexed gate for use in BooleanGraph.
+/// An indexed gate for use in BooleanGraph.
 /// Initially this gate can represent any type of gate or logic;
 /// however, this gate can be only of OR and AND type
 /// at the end of all simplifications and processing.
@@ -298,23 +301,23 @@ enum State : std::uint8_t {
 /// before any complex analysis is done.
 class Gate : public Node, public std::enable_shared_from_this<Gate> {
  public:
-  /// Argument entry type in the gate's argument containers.
+  /// An argument entry type in the gate's argument containers.
   /// The entry contains
   /// the positive or negative index (indicating a complement)
-  /// and a pointer to the argument node.
+  /// and the pointer to the argument node.
   ///
   /// @tparam T  The type of the argument node.
   template <class T>
   using Arg = std::pair<int, std::shared_ptr<T>>;
 
-  /// The associative container type to store the gate arguments.
-  /// This container type maps the index of the argument to a pointer to it.
+  /// An associative container type to store the gate arguments.
+  /// This container type maps the index of the argument to the pointer to it.
   ///
   /// @tparam T  The type of the argument node.
   template <class T>
   using ArgMap = ext::linear_map<int, std::shared_ptr<T>, ext::MoveEraser>;
 
-  /// The ordered set of gate argument indices.
+  /// An ordered set of gate argument indices.
   using ArgSet = boost::container::flat_set<int>;
 
   /// Creates an indexed gate with its unique index.
@@ -754,65 +757,7 @@ inline const Gate::ArgMap<Constant>& Gate::args<Constant>() const {
   return constant_args_;
 }
 
-/// Container of unique gates.
-/// This container acts like an unordered set of gates.
-/// The gates are equivalent
-/// if they have the same semantics.
-/// However, this set does not test
-/// for the isomorphism of the gates' Boolean formulas.
-class GateSet {
- public:
-  /// Inserts a gate into the set
-  /// if it is semantically unique.
-  ///
-  /// @param[in] gate  The gate to insert.
-  ///
-  /// @returns A pair of the unique gate and
-  ///          the insertion success flag.
-  std::pair<GatePtr, bool> insert(const GatePtr& gate) noexcept {
-    auto result = table_[gate->type()].insert(gate);
-    return {*result.first, result.second};
-  }
-
- private:
-  /// Functor for hashing gates by their arguments.
-  ///
-  /// @note The hashing discards the logic of the gate.
-  struct Hash {
-    /// Operator overload for hashing.
-    ///
-    /// @param[in] gate  The gate which hash must be calculated.
-    ///
-    /// @returns Hash value of the gate
-    ///          from its arguments but not logic.
-    std::size_t operator()(const GatePtr& gate) const noexcept {
-      return boost::hash_range(gate->args().begin(), gate->args().end());
-    }
-  };
-  /// Functor for equality test for gates by their arguments.
-  ///
-  /// @note The equality discards the logic of the gate.
-  struct Equal {
-    /// Operator overload for gate argument equality test.
-    ///
-    /// @param[in] lhs  The first gate.
-    /// @param[in] rhs  The second gate.
-    ///
-    /// @returns true if the gate arguments are equal.
-    bool operator()(const GatePtr& lhs, const GatePtr& rhs) const noexcept {
-      assert(lhs->type() == rhs->type());
-      if (lhs->args() != rhs->args())
-        return false;
-      if (lhs->type() == kVote && lhs->vote_number() != rhs->vote_number())
-        return false;
-      return true;
-    }
-  };
-  /// Container of gates grouped by their types.
-  std::array<std::unordered_set<GatePtr, Hash, Equal>, kNumOperators> table_;
-};
-
-class Preprocessor;
+class Preprocessor;  ///< @todo This can be decoupled.
 
 /// BooleanGraph is a propositional directed acyclic graph (PDAG).
 /// This class provides a simpler representation of a fault tree
@@ -885,7 +830,7 @@ class BooleanGraph : private boost::noncopyable {
     return basic_events_[index - 1];
   }
 
-  /// Prints the Boolean graph in the shorthand format.
+  /// Prints the Boolean graph in the Aralia format.
   /// This is a helper for logging and debugging.
   /// The output is the standard error.
   ///
@@ -1082,14 +1027,14 @@ class BooleanGraph : private boost::noncopyable {
   std::vector<std::weak_ptr<Gate>> null_gates_;
 };
 
-/// Prints Boolean graph nodes in the shorthand format.
+/// Prints Boolean graph nodes in the Aralia format.
 /// @{
 std::ostream& operator<<(std::ostream& os, const ConstantPtr& constant);
 std::ostream& operator<<(std::ostream& os, const VariablePtr& variable);
 std::ostream& operator<<(std::ostream& os, const GatePtr& gate);
 /// @}
 
-/// Prints the BooleanGraph as a fault tree in the shorthand format.
+/// Prints the BooleanGraph as a fault tree in the Aralia format.
 /// This function is mostly for debugging purposes.
 /// The output is not meant to be human readable.
 ///
diff --git a/src/ccf_group.cc b/src/ccf_group.cc
index d1400c7..04a0269 100644
--- a/src/ccf_group.cc
+++ b/src/ccf_group.cc
@@ -22,6 +22,9 @@
 
 #include <boost/range/algorithm.hpp>
 
+#include "expression/arithmetic.h"
+#include "expression/constant.h"
+
 namespace scram {
 namespace mef {
 
@@ -283,16 +286,19 @@ CcfGroup::ExpressionMap AlphaFactorModel::CalculateProbabilities() {
   assert(CcfGroup::factors().size() == max_level);
   std::vector<ExpressionPtr> sum_args;
   for (const std::pair<int, ExpressionPtr>& factor : CcfGroup::factors()) {
-    sum_args.push_back(factor.second);
+    sum_args.emplace_back(new Mul(
+        {ExpressionPtr(new ConstantExpression(factor.first)), factor.second}));
   }
   ExpressionPtr sum(new Add(std::move(sum_args)));
   int num_members = CcfGroup::members().size();
 
   for (int i = 0; i < max_level; ++i) {
     double mult = CalculateCombinationReciprocal(num_members - 1, i);
-    ExpressionPtr k(new ConstantExpression(mult));
+    ExpressionPtr level(new ConstantExpression(i + 1));
     ExpressionPtr fraction(new Div({CcfGroup::factors()[i].second, sum}));
-    ExpressionPtr prob(new Mul({k, fraction, CcfGroup::distribution()}));
+    ExpressionPtr prob(
+        new Mul({level, ExpressionPtr(new ConstantExpression(mult)), fraction,
+                 CcfGroup::distribution()}));
     probabilities.emplace_back(i + 1, prob);
   }
   assert(probabilities.size() == max_level);
diff --git a/src/ccf_group.h b/src/ccf_group.h
index 339128c..cb94d44 100644
--- a/src/ccf_group.h
+++ b/src/ccf_group.h
@@ -219,7 +219,7 @@ class AlphaFactorModel : public CcfGroup {
 /// Phi factor model is a simplification,
 /// where fractions of k-member group failure is given directly.
 /// Thus, Q_k = phi_k * Q_total.
-/// This model is described in the OpenPSA Model Exchange Format.
+/// This model is described in the Open-PSA Model Exchange Format.
 class PhiFactorModel : public CcfGroup {
  public:
   using CcfGroup::CcfGroup;
diff --git a/src/cycle.h b/src/cycle.h
index 6b70aeb..e5fd066 100644
--- a/src/cycle.h
+++ b/src/cycle.h
@@ -21,13 +21,11 @@
 #ifndef SCRAM_SRC_CYCLE_H_
 #define SCRAM_SRC_CYCLE_H_
 
-#include <cassert>
-
 #include <string>
 #include <vector>
 
 #include "event.h"
-#include "expression.h"
+#include "parameter.h"
 
 namespace scram {
 namespace mef {
diff --git a/src/event.h b/src/event.h
index 8091bbf..7f6fbec 100644
--- a/src/event.h
+++ b/src/event.h
@@ -23,7 +23,6 @@
 
 #include <cstdint>
 
-#include <array>
 #include <memory>
 #include <string>
 #include <vector>
@@ -319,8 +318,8 @@ const int kNumOperators = 8;
 
 /// String representations of the operators.
 /// The ordering is the same as the Operator enum.
-const std::array<const char*, kNumOperators> kOperatorToString = {
-    "and", "or", "atleast", "xor", "not", "nand", "nor", "null"};
+const char* const kOperatorToString[] = {"and", "or",   "atleast", "xor",
+                                         "not", "nand", "nor",     "null"};
 
 /// Boolean formula with operators and arguments.
 /// Formulas are not expected to be shared.
diff --git a/src/expression.cc b/src/expression.cc
index daa3bf2..8dbfcac 100644
--- a/src/expression.cc
+++ b/src/expression.cc
@@ -16,19 +16,11 @@
  */
 
 /// @file expression.cc
-/// Implementation of various expressions
-/// for basic event probability description.
+/// Implementation of the expression base class.
 
 #include "expression.h"
 
-#include <algorithm>
-
-#include <boost/math/constants/constants.hpp>
-#include <boost/range/algorithm.hpp>
-
-#include "error.h"
 #include "ext.h"
-#include "random.h"
 
 namespace scram {
 namespace mef {
@@ -59,474 +51,5 @@ bool Expression::IsConstant() noexcept {
       args_, [](const ExpressionPtr& arg) { return arg->IsConstant(); });
 }
 
-Parameter::Parameter(std::string name, std::string base_path,
-                     RoleSpecifier role)
-    : Expression({}),
-      Element(std::move(name)),
-      Role(role, std::move(base_path)),
-      Id(*this, *this),
-      unit_(kUnitless),
-      unused_(true),
-      expression_(nullptr) {}
-
-void Parameter::expression(const ExpressionPtr& expression) {
-  if (expression_)
-    throw LogicError("Parameter expression is already set.");
-  expression_ = expression.get();
-  Expression::AddArg(expression);
-}
-
-MissionTime::MissionTime()
-    : Expression({}),
-      mission_time_(-1),
-      unit_(kHours) {}
-
-const ExpressionPtr ConstantExpression::kOne(new ConstantExpression(1));
-const ExpressionPtr ConstantExpression::kZero(new ConstantExpression(0));
-const ExpressionPtr ConstantExpression::kPi(
-    new ConstantExpression(boost::math::constants::pi<double>()));
-
-ConstantExpression::ConstantExpression(double val)
-    : Expression({}),
-      value_(val) {}
-
-ConstantExpression::ConstantExpression(int val)
-    : Expression({}),
-      value_(val) {}
-
-ConstantExpression::ConstantExpression(bool val)
-    : Expression({}),
-      value_(val) {}
-
-ExponentialExpression::ExponentialExpression(const ExpressionPtr& lambda,
-                                             const ExpressionPtr& t)
-    : Expression({lambda, t}),
-      lambda_(*lambda),
-      time_(*t) {}
-
-void ExponentialExpression::Validate() const {
-  if (lambda_.Mean() < 0) {
-    throw InvalidArgument("The rate of failure cannot be negative.");
-  } else if (time_.Mean() < 0) {
-    throw InvalidArgument("The mission time cannot be negative.");
-  } else if (lambda_.Min() < 0) {
-    throw InvalidArgument("The sampled rate of failure cannot be negative.");
-  } else if (time_.Min() < 0) {
-    throw InvalidArgument("The sampled mission time cannot be negative.");
-  }
-}
-
-GlmExpression::GlmExpression(const ExpressionPtr& gamma,
-                             const ExpressionPtr& lambda,
-                             const ExpressionPtr& mu,
-                             const ExpressionPtr& t)
-    : Expression({gamma, lambda, mu, t}),
-      gamma_(*gamma),
-      lambda_(*lambda),
-      mu_(*mu),
-      time_(*t) {}
-
-void GlmExpression::Validate() const {
-  if (lambda_.Mean() < 0) {
-    throw InvalidArgument("The rate of failure cannot be negative.");
-  } else if (mu_.Mean() < 0) {
-    throw InvalidArgument("The rate of repair cannot be negative.");
-  } else if (gamma_.Mean() < 0 || gamma_.Mean() > 1) {
-    throw InvalidArgument("Invalid value for probability.");
-  } else if (time_.Mean() < 0) {
-    throw InvalidArgument("The mission time cannot be negative.");
-  } else if (lambda_.Min() < 0) {
-    throw InvalidArgument("The sampled rate of failure cannot be negative.");
-  } else if (mu_.Min() < 0) {
-    throw InvalidArgument("The sampled rate of repair cannot be negative.");
-  } else if (gamma_.Min() < 0 || gamma_.Max() > 1) {
-    throw InvalidArgument("Invalid sampled gamma value for probability.");
-  } else if (time_.Min() < 0) {
-    throw InvalidArgument("The sampled mission time cannot be negative.");
-  }
-}
-
-double GlmExpression::Mean() noexcept {
-  return Compute(gamma_.Mean(), lambda_.Mean(), mu_.Mean(), time_.Mean());
-}
-
-double GlmExpression::GetSample() noexcept {
-  return Compute(gamma_.Sample(), lambda_.Sample(), mu_.Sample(),
-                 time_.Sample());
-}
-
-double GlmExpression::Compute(double gamma, double lambda, double mu,
-                              double time) noexcept {
-  double r = lambda + mu;
-  return (lambda - (lambda - gamma * r) * std::exp(-r * time)) / r;
-}
-
-WeibullExpression::WeibullExpression(const ExpressionPtr& alpha,
-                                     const ExpressionPtr& beta,
-                                     const ExpressionPtr& t0,
-                                     const ExpressionPtr& time)
-    : Expression({alpha, beta, t0, time}),
-      alpha_(*alpha),
-      beta_(*beta),
-      t0_(*t0),
-      time_(*time) {}
-
-void WeibullExpression::Validate() const {
-  if (alpha_.Mean() <= 0) {
-    throw InvalidArgument("The scale parameter for Weibull distribution must"
-                          " be positive.");
-  } else if (beta_.Mean() <= 0) {
-    throw InvalidArgument("The shape parameter for Weibull distribution must"
-                          " be positive.");
-  } else if (t0_.Mean() < 0) {
-    throw InvalidArgument("Invalid value for time shift.");
-  } else if (time_.Mean() < 0) {
-    throw InvalidArgument("The mission time cannot be negative.");
-  } else if (time_.Mean() < t0_.Mean()) {
-    throw InvalidArgument("The mission time must be longer than time shift.");
-  } else if (alpha_.Min() <= 0) {
-    throw InvalidArgument("The scale parameter for Weibull distribution must"
-                          " be positive for sampled values.");
-  } else if (beta_.Min() <= 0) {
-    throw InvalidArgument("The shape parameter for Weibull distribution must"
-                          " be positive for sampled values.");
-  } else if (t0_.Min() < 0) {
-    throw InvalidArgument("Invalid value for time shift in sampled values.");
-  } else if (time_.Min() < 0) {
-    throw InvalidArgument("The sampled mission time cannot be negative.");
-  } else if (time_.Min() < t0_.Max()) {
-    throw InvalidArgument("The sampled mission time must be"
-                          " longer than time shift.");
-  }
-}
-
-double WeibullExpression::Compute(double alpha, double beta,
-                                  double t0, double time) noexcept {
-  return 1 - std::exp(-std::pow((time - t0) / alpha, beta));
-}
-
-UniformDeviate::UniformDeviate(const ExpressionPtr& min,
-                               const ExpressionPtr& max)
-    : RandomDeviate({min, max}),
-      min_(*min),
-      max_(*max) {}
-
-void UniformDeviate::Validate() const {
-  if (min_.Mean() >= max_.Mean()) {
-    throw InvalidArgument("Min value is more than max for Uniform"
-                          " distribution.");
-  } else if (min_.Max() >= max_.Min()) {
-    throw InvalidArgument("Sampled min value is more than sampled max"
-                          " for Uniform distribution.");
-  }
-}
-
-double UniformDeviate::GetSample() noexcept {
-  return Random::UniformRealGenerator(min_.Sample(), max_.Sample());
-}
-
-NormalDeviate::NormalDeviate(const ExpressionPtr& mean,
-                             const ExpressionPtr& sigma)
-    : RandomDeviate({mean, sigma}),
-      mean_(*mean),
-      sigma_(*sigma) {}
-
-void NormalDeviate::Validate() const {
-  if (sigma_.Mean() <= 0) {
-    throw InvalidArgument("Standard deviation cannot be negative or zero.");
-  } else if (sigma_.Min() <= 0) {
-    throw InvalidArgument("Sampled standard deviation is negative or zero.");
-  }
-}
-
-double NormalDeviate::GetSample() noexcept {
-  return Random::NormalGenerator(mean_.Sample(), sigma_.Sample());
-}
-
-LogNormalDeviate::LogNormalDeviate(const ExpressionPtr& mean,
-                                   const ExpressionPtr& ef,
-                                   const ExpressionPtr& level)
-    : RandomDeviate({mean, ef, level}),
-      mean_(*mean),
-      ef_(*ef),
-      level_(*level) {}
-
-void LogNormalDeviate::Validate() const {
-  if (level_.Mean() <= 0 || level_.Mean() >= 1) {
-    throw InvalidArgument("The confidence level is not within (0, 1).");
-  } else if (ef_.Mean() <= 1) {
-    throw InvalidArgument("The Error Factor for Log-Normal distribution"
-                          " cannot be less than 1.");
-  } else if (mean_.Mean() <= 0) {
-    throw InvalidArgument("The mean of Log-Normal distribution cannot be"
-                          " negative or zero.");
-  } else if (level_.Min() <= 0 || level_.Max() >= 1) {
-    throw InvalidArgument("The confidence level doesn't sample within (0, 1).");
-
-  } else if (ef_.Min() <= 1) {
-    throw InvalidArgument("The Sampled Error Factor for Log-Normal"
-                          " distribution cannot be less than 1.");
-  } else if (mean_.Min() <= 0) {
-    throw InvalidArgument("The sampled mean of Log-Normal distribution"
-                          " cannot be negative or zero.");
-  }
-}
-
-double LogNormalDeviate::GetSample() noexcept {
-  double sigma = ComputeScale(level_.Sample(), ef_.Sample());
-  double mu = ComputeLocation(mean_.Sample(), sigma);
-  return Random::LogNormalGenerator(mu, sigma);
-}
-
-double LogNormalDeviate::Max() noexcept {
-  double sigma = ComputeScale(level_.Mean(), ef_.Mean());
-  double mu = ComputeLocation(mean_.Max(), sigma);
-  return std::exp(
-      std::sqrt(2) * std::pow(boost::math::erfc(1 / 50), -1) * sigma + mu);
-}
-
-double LogNormalDeviate::ComputeScale(double level, double ef) noexcept {
-  double p = level + (1 - level) / 2;
-  double z = std::sqrt(2) * boost::math::erfc_inv(2 * p);
-  return std::log(ef) / std::abs(z);
-}
-
-double LogNormalDeviate::ComputeLocation(double mean, double sigma) noexcept {
-  return std::log(mean) - std::pow(sigma, 2) / 2;
-}
-
-GammaDeviate::GammaDeviate(const ExpressionPtr& k, const ExpressionPtr& theta)
-    : RandomDeviate({k, theta}),
-      k_(*k),
-      theta_(*theta) {}
-
-void GammaDeviate::Validate() const {
-  if (k_.Mean() <= 0) {
-    throw InvalidArgument("The k shape parameter for Gamma distribution"
-                          " cannot be negative or zero.");
-  } else if (theta_.Mean() <= 0) {
-    throw InvalidArgument("The theta scale parameter for Gamma distribution"
-                          " cannot be negative or zero.");
-  } else if (k_.Min() <= 0) {
-    throw InvalidArgument("Sampled k shape parameter for Gamma distribution"
-                          " cannot be negative or zero.");
-  } else if (theta_.Min() <= 0) {
-    throw InvalidArgument("Sampled theta scale parameter for Gamma "
-                          "distribution cannot be negative or zero.");
-  }
-}
-
-double GammaDeviate::GetSample() noexcept {
-  return Random::GammaGenerator(k_.Sample(), theta_.Sample());
-}
-
-BetaDeviate::BetaDeviate(const ExpressionPtr& alpha, const ExpressionPtr& beta)
-    : RandomDeviate({alpha, beta}),
-      alpha_(*alpha),
-      beta_(*beta) {}
-
-void BetaDeviate::Validate() const {
-  if (alpha_.Mean() <= 0) {
-    throw InvalidArgument("The alpha shape parameter for Beta distribution"
-                          " cannot be negative or zero.");
-  } else if (beta_.Mean() <= 0) {
-    throw InvalidArgument("The beta shape parameter for Beta distribution"
-                          " cannot be negative or zero.");
-  } else if (alpha_.Min() <= 0) {
-    throw InvalidArgument("Sampled alpha shape parameter for"
-                          " Beta distribution cannot be negative or zero.");
-  } else if (beta_.Min() <= 0) {
-    throw InvalidArgument("Sampled beta shape parameter for Beta"
-                          " distribution cannot be negative or zero.");
-  }
-}
-
-double BetaDeviate::GetSample() noexcept {
-  return Random::BetaGenerator(alpha_.Sample(), beta_.Sample());
-}
-
-Histogram::Histogram(std::vector<ExpressionPtr> boundaries,
-                     std::vector<ExpressionPtr> weights)
-    : RandomDeviate(std::move(boundaries)) {  // Partial registration!
-  int num_intervals = Expression::args().size() - 1;
-  if (weights.size() != num_intervals) {
-    throw InvalidArgument("The number of weights is not equal to the number"
-                          " of intervals.");
-  }
-
-  // Complete the argument registration.
-  for (const ExpressionPtr& arg : weights)
-    Expression::AddArg(arg);
-
-  boundaries_.first = Expression::args().begin();
-  boundaries_.second = std::next(boundaries_.first, num_intervals + 1);
-  weights_.first = boundaries_.second;
-  weights_.second = Expression::args().end();
-}
-
-double Histogram::Mean() noexcept {
-  double sum_weights = 0;
-  double sum_product = 0;
-  auto it_b = boundaries_.first;
-  double prev_bound = (*it_b++)->Mean();
-  for (auto it_w = weights_.first; it_w != weights_.second; ++it_w, ++it_b) {
-    double cur_bound = (*it_b)->Mean();
-    double cur_weight = (*it_w)->Mean();
-    sum_product += (cur_bound - prev_bound) * cur_weight;
-    sum_weights += cur_weight;
-    prev_bound = cur_bound;
-  }
-  return sum_product / (prev_bound * sum_weights);
-}
-
-namespace {
-
-/// Iterator adaptor for retrieving sampled values.
-template <class Iterator>
-class sampler_iterator : public Iterator {
- public:
-  /// Initializes the wrapper with to-be-sampled iterator.
-  explicit sampler_iterator(const Iterator& it) : Iterator(it) {}
-
-  /// Hides the wrapped iterator's operator*.
-  ///
-  /// @returns The sampled value of the expression under the iterator.
-  double operator*() { return Iterator::operator*()->Sample(); }
-};
-
-/// Helper function for type deduction upon sampler_iterator construction.
-template <class Iterator>
-sampler_iterator<Iterator> make_sampler(const Iterator& it) {
-  return sampler_iterator<Iterator>(it);
-}
-
-}  // namespace
-
-double Histogram::GetSample() noexcept {
-#ifdef _LIBCPP_VERSION  // libc++ chokes on iterator categories.
-  std::vector<double> samples;
-  for (auto it = boundaries_.first; it != boundaries_.second; ++it) {
-    samples.push_back((*it)->Sample());
-  }
-  return Random::HistogramGenerator(
-      samples.begin(), samples.end(), make_sampler(weights_.first));
-#else
-  return Random::HistogramGenerator(make_sampler(boundaries_.first),
-                                    make_sampler(boundaries_.second),
-                                    make_sampler(weights_.first));
-#endif
-}
-
-void Histogram::CheckBoundaries() const {
-  auto it = boundaries_.first;
-  if ((*it)->IsConstant() == false || (*it)->Mean() != 0) {
-    throw InvalidArgument("Histogram lower boundary must be 0.");
-  }
-  for (++it; it != boundaries_.second; ++it) {
-    const auto& prev_expr = *std::prev(it);
-    const auto& cur_expr = *it;
-    if (prev_expr->Mean() >= cur_expr->Mean()) {
-      throw InvalidArgument("Histogram upper boundaries are not strictly"
-                            " increasing and positive.");
-    } else if (prev_expr->Max() >= cur_expr->Min()) {
-      throw InvalidArgument("Histogram sampled upper boundaries must"
-                            " be strictly increasing and positive.");
-    }
-  }
-}
-
-void Histogram::CheckWeights() const {
-  for (auto it = weights_.first; it != weights_.second; ++it) {
-    if ((*it)->Mean() < 0) {
-      throw InvalidArgument("Histogram weights can't be negative.");
-    } else if ((*it)->Min() < 0) {
-      throw InvalidArgument("Histogram sampled weights can't be negative.");
-    }
-  }
-}
-
-Neg::Neg(const ExpressionPtr& expression)
-    : Expression({expression}),
-      expression_(*expression) {}
-
-BinaryExpression::BinaryExpression(std::vector<ExpressionPtr> args)
-    : Expression(std::move(args)) {
-  if (Expression::args().size() < 2)
-    throw InvalidArgument("Expression requires 2 or more arguments.");
-}
-
-double Mul::Mean() noexcept {
-  double mean = 1;
-  for (const ExpressionPtr& arg : Expression::args())
-    mean *= arg->Mean();
-  return mean;
-}
-
-double Mul::GetSample() noexcept {
-  double result = 1;
-  for (const ExpressionPtr& arg : Expression::args())
-    result *= arg->Sample();
-  return result;
-}
-
-double Mul::GetExtremum(bool maximum) noexcept {
-  double max_val = 1;  // Maximum possible product.
-  double min_val = 1;  // Minimum possible product.
-  for (const ExpressionPtr& arg : Expression::args()) {
-    double mult_max = arg->Max();
-    double mult_min = arg->Min();
-    double max_max = max_val * mult_max;
-    double max_min = max_val * mult_min;
-    double min_max = min_val * mult_max;
-    double min_min = min_val * mult_min;
-    max_val = std::max({max_max, max_min, min_max, min_min});
-    min_val = std::min({max_max, max_min, min_max, min_min});
-  }
-  return maximum ? max_val : min_val;
-}
-
-void Div::Validate() const {
-  auto it = Expression::args().begin();
-  for (++it; it != Expression::args().end(); ++it) {
-    const auto& expr = *it;
-    if (!expr->Mean() || !expr->Max() || !expr->Min())
-      throw InvalidArgument("Division by 0.");
-  }
-}
-
-double Div::Mean() noexcept {
-  auto it = Expression::args().begin();
-  double mean = (*it)->Mean();
-  for (++it; it != Expression::args().end(); ++it) {
-    mean /= (*it)->Mean();
-  }
-  return mean;
-}
-
-double Div::GetSample() noexcept {
-  auto it = Expression::args().begin();
-  double result = (*it)->Sample();
-  for (++it; it != Expression::args().end(); ++it)
-    result /= (*it)->Sample();
-  return result;
-}
-
-double Div::GetExtremum(bool maximum) noexcept {
-  auto it = Expression::args().begin();
-  double max_value = (*it)->Max();  // Maximum possible result.
-  double min_value = (*it)->Min();  // Minimum possible result.
-  for (++it; it != Expression::args().end(); ++it) {
-    double div_max = (*it)->Max();
-    double div_min = (*it)->Min();
-    double max_max = max_value / div_max;
-    double max_min = max_value / div_min;
-    double min_max = min_value / div_max;
-    double min_min = min_value / div_min;
-    max_value = std::max({max_max, max_min, min_max, min_min});
-    min_value = std::min({max_max, max_min, min_max, min_min});
-  }
-  return maximum ? max_value : min_value;
-}
-
 }  // namespace mef
 }  // namespace scram
diff --git a/src/expression.h b/src/expression.h
index 3e3ed44..19a0d7e 100644
--- a/src/expression.h
+++ b/src/expression.h
@@ -16,23 +16,17 @@
  */
 
 /// @file expression.h
-/// Expressions that describe basic events.
+/// Provides the base class for all expressions
+/// and units for expression values.
 
 #ifndef SCRAM_SRC_EXPRESSION_H_
 #define SCRAM_SRC_EXPRESSION_H_
 
-#include <cmath>
 #include <cstdint>
 
-#include <array>
 #include <memory>
-#include <string>
-#include <utility>
 #include <vector>
 
-#include <boost/math/special_functions/beta.hpp>
-#include <boost/math/special_functions/erf.hpp>
-#include <boost/math/special_functions/gamma.hpp>
 #include <boost/noncopyable.hpp>
 
 #include "element.h"
@@ -153,653 +147,12 @@ enum Units : std::uint8_t {
   kDemands
 };
 
-/// The number of elements in the Units enum.
-const int kNumUnits = 10;
+const int kNumUnits = 10;  ///< The number of elements in the Units enum.
 
 /// String representations of the Units in the same order as the enum.
-const std::array<const char*, kNumUnits> kUnitsToString = {
-    "unitless", "bool",  "int",     "float", "hours",
-    "hours-1",  "years", "years-1", "fit",   "demands"};
-
-/// This class provides a representation of a variable
-/// in basic event description.
-/// It is both expression and element description.
-class Parameter : public Expression,
-                  public Element,
-                  public Role,
-                  public Id,
-                  public NodeMark {
- public:
-  /// Creates a parameter as a variable for future references.
-  ///
-  /// @param[in] name  The name of this variable (Case sensitive).
-  /// @param[in] base_path  The series of containers to get this parameter.
-  /// @param[in] role  The role of the parameter within the model or container.
-  ///
-  /// @throws LogicError  The name is empty.
-  /// @throws InvalidArgument  The name or reference paths are malformed.
-  explicit Parameter(std::string name, std::string base_path = "",
-                     RoleSpecifier role = RoleSpecifier::kPublic);
-
-  /// Sets the expression of this parameter.
-  ///
-  /// @param[in] expression  The expression to describe this parameter.
-  ///
-  /// @throws LogicError  The parameter expression is already set.
-  void expression(const ExpressionPtr& expression);
-
-  /// @returns The unit of this parameter.
-  Units unit() const { return unit_; }
-
-  /// Sets the unit of this parameter.
-  ///
-  /// @param[in] unit  A valid unit.
-  void unit(Units unit) { unit_ = unit; }
-
-  /// @returns The usage state of this parameter.
-  bool unused() { return unused_; }
-
-  /// Sets the usage state for this parameter.
-  ///
-  /// @param[in] state  The usage state for this parameter.
-  void unused(bool state) { unused_ = state; }
-
-  double Mean() noexcept override { return expression_->Mean(); }
-  double Max() noexcept override { return expression_->Max(); }
-  double Min() noexcept override { return expression_->Min(); }
-
- private:
-  double GetSample() noexcept override { return expression_->Sample(); }
-
-  Units unit_;  ///< Units of this parameter.
-  bool unused_;  ///< Usage state.
-  Expression* expression_;  ///< Expression for this parameter.
-};
-
-using ParameterPtr = std::shared_ptr<Parameter>;  ///< Shared parameters.
-
-/// This is for the system mission time.
-class MissionTime : public Expression {
- public:
-  MissionTime();
-
-  /// Sets the mission time.
-  /// This function is expected to be used only once.
-  ///
-  /// @param[in] time  The mission time.
-  void mission_time(double time) {
-    assert(time >= 0);
-    mission_time_ = time;
-  }
-
-  /// @returns The unit of the system mission time.
-  Units unit() const { return unit_; }
-
-  /// Sets the unit of this parameter.
-  ///
-  /// @param[in] unit  A valid unit.
-  void unit(Units unit) { unit_ = unit; }
-
-  double Mean() noexcept override { return mission_time_; }
-  bool IsConstant() noexcept override { return true; }
-
- private:
-  double GetSample() noexcept override { return mission_time_; }
-
-  double mission_time_;  ///< The system mission time.
-  Units unit_;  ///< Units of this parameter.
-};
-
-/// Indicates a constant value.
-class ConstantExpression : public Expression {
- public:
-  static const ExpressionPtr kOne;  ///< Constant 1 or True.
-  static const ExpressionPtr kZero;  ///< Constant 0 or False.
-  static const ExpressionPtr kPi;  ///< Constant PI value.
-
-  /// Constructor for numerical values.
-  ///
-  /// @param[in] val  Float numerical value.
-  explicit ConstantExpression(double val);
-
-  /// Constructor for numerical values.
-  ///
-  /// @param[in] val  Integer numerical value.
-  explicit ConstantExpression(int val);
-
-  /// Constructor for boolean values.
-  ///
-  /// @param[in] val  true for 1 and false for 0 value of this constant.
-  explicit ConstantExpression(bool val);
-
-  double Mean() noexcept override { return value_; }
-  bool IsConstant() noexcept override { return true; }
-
- private:
-  double GetSample() noexcept override { return value_; }
-  double value_;  ///< The Constant value.
-};
-
-/// Negative exponential distribution
-/// with hourly failure rate and time.
-class ExponentialExpression : public Expression {
- public:
-  /// Constructor for exponential expression with two arguments.
-  ///
-  /// @param[in] lambda  Hourly rate of failure.
-  /// @param[in] t  Mission time in hours.
-  ExponentialExpression(const ExpressionPtr& lambda, const ExpressionPtr& t);
-
-  /// @throws InvalidArgument  The failure rate or time is negative.
-  void Validate() const override;
-
-  double Mean() noexcept override {
-    return 1 - std::exp(-(lambda_.Mean() * time_.Mean()));
-  }
-
-  double Max() noexcept override {
-    return 1 - std::exp(-(lambda_.Max() * time_.Max()));
-  }
-
-  double Min() noexcept override {
-    return 1 - std::exp(-(lambda_.Min() * time_.Min()));
-  }
-
- private:
-  double GetSample() noexcept override {
-    return 1 - std::exp(-(lambda_.Sample() * time_.Sample()));
-  }
-
-  Expression& lambda_;  ///< Failure rate in hours.
-  Expression& time_;  ///< Mission time in hours.
-};
-
-/// Exponential with probability of failure on demand,
-/// hourly failure rate, hourly repairing rate, and time.
-///
-/// @todo Find the minimum and maximum values.
-class GlmExpression : public Expression {
- public:
-  /// Constructor for GLM or exponential expression with four arguments.
-  ///
-  /// @param[in] gamma  Probability of failure on demand.
-  /// @param[in] lambda  Hourly rate of failure.
-  /// @param[in] mu  Hourly repairing rate.
-  /// @param[in] t  Mission time in hours.
-  GlmExpression(const ExpressionPtr& gamma, const ExpressionPtr& lambda,
-                const ExpressionPtr& mu, const ExpressionPtr& t);
-
-  void Validate() const override;
-
-  double Mean() noexcept override;
-  double Max() noexcept override { return 1; }
-  double Min() noexcept override { return 0; }
-
- private:
-  double GetSample() noexcept override;
-
-  /// Computes the value for GLM expression.
-  ///
-  /// @param[in] gamma  Value for probability on demand.
-  /// @param[in] lambda  Value for hourly rate of failure.
-  /// @param[in] mu  Value for hourly repair rate.
-  /// @param[in] time  Mission time in hours.
-  ///
-  /// @returns Probability of failure on demand.
-  double Compute(double gamma, double lambda, double mu, double time) noexcept;
-
-  Expression& gamma_;  ///< Probability of failure on demand.
-  Expression& lambda_;  ///< Failure rate in hours.
-  Expression& mu_;  ///< Repair rate in hours.
-  Expression& time_;  ///< Mission time in hours.
-};
-
-/// Weibull distribution with scale, shape, time shift, and time.
-class WeibullExpression : public Expression {
- public:
-  /// Constructor for Weibull distribution.
-  ///
-  /// @param[in] alpha  Scale parameter.
-  /// @param[in] beta  Shape parameter.
-  /// @param[in] t0  Time shift.
-  /// @param[in] time  Mission time.
-  WeibullExpression(const ExpressionPtr& alpha, const ExpressionPtr& beta,
-                    const ExpressionPtr& t0, const ExpressionPtr& time);
-
-  void Validate() const override;
-
-  double Mean() noexcept override {
-    return Compute(alpha_.Mean(), beta_.Mean(), t0_.Mean(), time_.Mean());
-  }
-
-  double Max() noexcept override {
-    return Compute(alpha_.Min(), beta_.Max(), t0_.Min(), time_.Max());
-  }
-
-  double Min() noexcept override {
-    return Compute(alpha_.Max(), beta_.Min(), t0_.Max(), time_.Min());
-  }
-
- private:
-  double GetSample() noexcept override {
-    return Compute(alpha_.Sample(), beta_.Sample(), t0_.Sample(),
-                   time_.Sample());
-  }
-
-  /// Calculates Weibull expression.
-  ///
-  /// @param[in] alpha  Scale parameter.
-  /// @param[in] beta  Shape parameter.
-  /// @param[in] t0  Time shift.
-  /// @param[in] time  Mission time.
-  ///
-  /// @returns Calculated value.
-  double Compute(double alpha, double beta, double t0, double time) noexcept;
-
-  Expression& alpha_;  ///< Scale parameter.
-  Expression& beta_;  ///< Shape parameter.
-  Expression& t0_;  ///< Time shift in hours.
-  Expression& time_;  ///< Mission time in hours.
-};
-
-/// Abstract base class for all deviate expressions.
-/// These expressions provide quantification for uncertainty and sensitivity.
-class RandomDeviate : public Expression {
- public:
-  using Expression::Expression;
-
-  bool IsConstant() noexcept override { return false; }
-};
-
-/// Uniform distribution.
-class UniformDeviate : public RandomDeviate {
- public:
-  /// Setup for uniform distribution.
-  ///
-  /// @param[in] min  Minimum value of the distribution.
-  /// @param[in] max  Maximum value of the distribution.
-  UniformDeviate(const ExpressionPtr& min, const ExpressionPtr& max);
-
-  /// @throws InvalidArgument  The min value is more or equal to max value.
-  void Validate() const override;
-
-  double Mean() noexcept override { return (min_.Mean() + max_.Mean()) / 2; }
-  double Max() noexcept override { return max_.Max(); }
-  double Min() noexcept override { return min_.Min(); }
-
- private:
-  double GetSample() noexcept override;
-
-  Expression& min_;  ///< Minimum value of the distribution.
-  Expression& max_;  ///< Maximum value of the distribution.
-};
-
-/// Normal distribution.
-class NormalDeviate : public RandomDeviate {
- public:
-  /// Setup for normal distribution.
-  ///
-  /// @param[in] mean  The mean of the distribution.
-  /// @param[in] sigma  The standard deviation of the distribution.
-  NormalDeviate(const ExpressionPtr& mean, const ExpressionPtr& sigma);
-
-  /// @throws InvalidArgument  The sigma is negative or zero.
-  void Validate() const override;
-
-  double Mean() noexcept override { return mean_.Mean(); }
-
-  /// @returns ~99.9% percentile value.
-  ///
-  /// @warning This is only an approximation of the maximum value.
-  double Max() noexcept override { return mean_.Max() + 6 * sigma_.Max(); }
-
-  /// @returns Less than 0.1% percentile value.
-  ///
-  /// @warning This is only an approximation.
-  double Min() noexcept override { return mean_.Min() - 6 * sigma_.Max(); }
-
- private:
-  double GetSample() noexcept override;
-
-  Expression& mean_;  ///< Mean value of normal distribution.
-  Expression& sigma_;  ///< Standard deviation of normal distribution.
-};
-
-/// Log-normal distribution.
-class LogNormalDeviate : public RandomDeviate {
- public:
-  /// Setup for log-normal distribution.
-  ///
-  /// @param[in] mean  The mean of the log-normal distribution
-  ///                  not the mean of underlying normal distribution,
-  ///                  which is parameter mu.
-  ///                  mu is the location parameter,
-  ///                  sigma is the scale factor.
-  ///                  E(x) = exp(mu + sigma^2 / 2)
-  /// @param[in] ef  The error factor of the log-normal distribution.
-  ///                EF = exp(z * sigma)
-  /// @param[in] level  The confidence level.
-  LogNormalDeviate(const ExpressionPtr& mean, const ExpressionPtr& ef,
-                   const ExpressionPtr& level);
-
-  /// @throws InvalidArgument  (mean <= 0) or (ef <= 0) or invalid level
-  void Validate() const override;
-
-  double Mean() noexcept override { return mean_.Mean(); }
-
-  /// 99 percentile estimate.
-  double Max() noexcept override;
-
-  double Min() noexcept override { return 0; }
-
- private:
-  double GetSample() noexcept override;
-
-  /// Computes the scale parameter of the distribution.
-  ///
-  /// @param[in] level  The confidence level.
-  /// @param[in] ef  The error factor of the log-normal distribution.
-  ///
-  /// @returns Scale parameter (sigma) value.
-  double ComputeScale(double level, double ef) noexcept;
-
-  /// Computes the location parameter of the distribution.
-  ///
-  /// @param[in] mean  The mean of the log-normal distribution.
-  /// @param[in] sigma  The scale parameter of the distribution.
-  ///
-  /// @returns Value of location parameter (mu) value.
-  double ComputeLocation(double mean, double sigma) noexcept;
-
-  Expression& mean_;  ///< Mean value of the log-normal distribution.
-  Expression& ef_;  ///< Error factor of the log-normal distribution.
-  Expression& level_;  ///< Confidence level of the log-normal distribution.
-};
-
-/// Gamma distribution.
-class GammaDeviate : public RandomDeviate {
- public:
-  /// Setup for Gamma distribution.
-  ///
-  /// @param[in] k  Shape parameter of Gamma distribution.
-  /// @param[in] theta  Scale parameter of Gamma distribution.
-  GammaDeviate(const ExpressionPtr& k, const ExpressionPtr& theta);
-
-  /// @throws InvalidArgument  (k <= 0) or (theta <= 0)
-  void Validate() const override;
-
-  double Mean() noexcept override { return k_.Mean() * theta_.Mean(); }
-
-  /// @returns 99 percentile.
-  double Max() noexcept override {
-    using boost::math::gamma_q;
-    double k_max = k_.Max();
-    return theta_.Max() *
-           std::pow(gamma_q(k_max, gamma_q(k_max, 0) - 0.99), -1);
-  }
-
-  double Min() noexcept override { return 0; }
-
- private:
-  double GetSample() noexcept override;
-
-  Expression& k_;  ///< The shape parameter of the gamma distribution.
-  Expression& theta_;  ///< The scale factor of the gamma distribution.
-};
-
-/// Beta distribution.
-class BetaDeviate : public RandomDeviate {
- public:
-  /// Setup for Beta distribution.
-  ///
-  /// @param[in] alpha  Alpha shape parameter of Gamma distribution.
-  /// @param[in] beta  Beta shape parameter of Gamma distribution.
-  BetaDeviate(const ExpressionPtr& alpha, const ExpressionPtr& beta);
-
-  /// @throws InvalidArgument  (alpha <= 0) or (beta <= 0)
-  void Validate() const override;
-
-  double Mean() noexcept override {
-    double alpha_mean = alpha_.Mean();
-    return alpha_mean / (alpha_mean + beta_.Mean());
-  }
-
-  /// @returns 99 percentile.
-  double Max() noexcept override {
-    return std::pow(boost::math::ibeta(alpha_.Max(), beta_.Max(), 0.99), -1);
-  }
-
-  double Min() noexcept override { return 0; }
-
- private:
-  double GetSample() noexcept override;
-
-  Expression& alpha_;  ///< The alpha shape parameter.
-  Expression& beta_;  ///< The beta shape parameter.
-};
-
-/// Histogram distribution.
-class Histogram : public RandomDeviate {
- public:
-  /// Histogram distribution setup.
-  ///
-  /// @param[in] boundaries  The bounds of intervals.
-  /// @param[in] weights  The positive weights of intervals
-  ///                     restricted by the upper boundaries.
-  ///                     Therefore, the number of weights must be
-  ///                     equal to the number of intervals.
-  ///
-  /// @throws InvalidArgument  The boundaries container size is not equal to
-  ///                          weights container size + 1.
-  ///
-  /// @note This description of histogram sampling is mostly for probabilities.
-  ///       Therefore, it is not flexible.
-  ///       Currently, it allows sampling both boundaries and weights.
-  ///       This behavior makes checking
-  ///       for valid arrangement of the boundaries mandatory
-  ///       for each sampling.
-  ///       Moreover, the first starting point is assumed but not defined.
-  ///       The starting point is assumed to be 0,
-  ///       which leaves only positive values for boundaries.
-  ///       This behavior is restrictive
-  ///       and should be handled accordingly.
-  Histogram(std::vector<ExpressionPtr> boundaries,
-            std::vector<ExpressionPtr> weights);
-
-  /// @throws InvalidArgument  The boundaries are not strictly increasing,
-  ///                          or weights are negative.
-  void Validate() const override {
-    CheckBoundaries();
-    CheckWeights();
-  }
-
-  double Mean() noexcept override;
-  double Max() noexcept override {
-    return (*std::prev(boundaries_.second))->Max();
-  }
-  double Min() noexcept override { return 0; }
-
- private:
-  /// Access to args.
-  using Iterator = std::vector<ExpressionPtr>::const_iterator;
-
-  double GetSample() noexcept override;
-
-  /// Checks if values of boundary expressions are strictly increasing.
-  ///
-  /// @throws InvalidArgument  The mean values are not strictly increasing.
-  void CheckBoundaries() const;
-
-  /// Checks if values of weights are non-negative.
-  ///
-  /// @throws InvalidArgument  The mean values are negative.
-  void CheckWeights() const;
-
-  std::pair<Iterator, Iterator> boundaries_;  ///< Boundaries of the intervals.
-  std::pair<Iterator, Iterator> weights_;  ///< Weights of the intervals.
-};
-
-/// This class for negation of numerical value or another expression.
-class Neg : public Expression {
- public:
-  /// Construct a new expression
-  /// that negates a given argument expression.
-  ///
-  /// @param[in] expression  The expression to be negated.
-  explicit Neg(const ExpressionPtr& expression);
-
-  double Mean() noexcept override { return -expression_.Mean(); }
-  double Max() noexcept override { return -expression_.Min(); }
-  double Min() noexcept override { return -expression_.Max(); }
-
- private:
-  double GetSample() noexcept override { return -expression_.Sample(); }
-
-  Expression& expression_;  ///< Expression that is used for negation.
-};
-
-/// Base class for expressions that require 2 or more arguments.
-class BinaryExpression : public Expression {
- public:
-  /// Checks the number of provided arguments upon initialization.
-  ///
-  /// @param[in] args  Arguments of this expression.
-  ///
-  /// @throws InvalidArgument  The number of arguments is fewer than 2.
-  explicit BinaryExpression(std::vector<ExpressionPtr> args);
-};
-
-/// This expression adds all the given expressions' values.
-class Add : public BinaryExpression {
- public:
-  using BinaryExpression::BinaryExpression;
-
-  double Mean() noexcept override { return Compute(&Expression::Mean); }
-  double Max() noexcept override { return Compute(&Expression::Max); }
-  double Min() noexcept override { return Compute(&Expression::Min); }
-
- private:
-  double GetSample() noexcept override {
-    return Compute(&Expression::Sample);
-  }
-
-  /// Adds all argument expression values.
-  ///
-  /// @param[in] value  The getter function for the arg expression value.
-  ///
-  /// @returns The sum of the expression values.
-  double Compute(double (Expression::*value)()) {
-    double result = 0;
-    for (const ExpressionPtr& arg : Expression::args())
-      result += ((*arg).*value)();
-    return result;
-  }
-};
-
-/// This expression performs subtraction operation.
-/// First expression minus the rest of the given expressions' values.
-class Sub : public BinaryExpression {
- public:
-  using BinaryExpression::BinaryExpression;
-
-  double Mean() noexcept override { return Compute(&Expression::Mean); }
-  double Max() noexcept override {
-    return Compute(&Expression::Max, &Expression::Min);
-  }
-  double Min() noexcept override {
-    return Compute(&Expression::Min, &Expression::Max);
-  }
-
- private:
-  double GetSample() noexcept override {
-    return Compute(&Expression::Sample);
-  }
-
-  /// Performs the subtraction of all argument expression values.
-  ///
-  /// @param[in] first_value  The getter function for the first arg expression.
-  /// @param[in] rest_value  The getter function for the rest arg expressions.
-  ///                        If not given, it is equal to first_value.
-  ///
-  /// @returns first_value() - sum(rest_value()).
-  double Compute(double (Expression::*first_value)(),
-                 double (Expression::*rest_value)() = nullptr) {
-    if (!rest_value)
-      rest_value = first_value;
-
-    auto it = Expression::args().begin();
-    double result = ((**it).*first_value)();
-    for (++it; it != Expression::args().end(); ++it) {
-      result -= ((**it).*rest_value)();
-    }
-    return result;
-  }
-};
-
-/// This expression performs multiplication operation.
-class Mul : public BinaryExpression {
- public:
-  using BinaryExpression::BinaryExpression;
-
-  double Mean() noexcept override;
-
-  /// Finds maximum product
-  /// from the given arguments' minimum and maximum values.
-  /// Negative values may introduce sign cancellation.
-  ///
-  /// @returns Maximum possible value of the product.
-  double Max() noexcept override { return GetExtremum(/*max=*/true); }
-
-  /// Finds minimum product
-  /// from the given arguments' minimum and maximum values.
-  /// Negative values may introduce sign cancellation.
-  ///
-  /// @returns Minimum possible value of the product.
-  double Min() noexcept override { return GetExtremum(/*max=*/false); }
-
- private:
-  double GetSample() noexcept override;
-
-  /// @param[in] maximum  Flag to return maximum value.
-  ///
-  /// @returns One of extremums.
-  double GetExtremum(bool maximum) noexcept;
-};
-
-/// This expression performs division operation.
-/// The expression divides the first given argument by
-/// the rest of argument expressions.
-class Div : public BinaryExpression {
- public:
-  using BinaryExpression::BinaryExpression;
-
-  /// @throws InvalidArgument  Division by 0.
-  void Validate() const override;
-
-  double Mean() noexcept override;
-
-  /// Finds maximum results of division
-  /// of the given arguments' minimum and maximum values.
-  /// Negative values may introduce sign cancellation.
-  ///
-  /// @returns Maximum value for division of arguments.
-  double Max() noexcept override { return GetExtremum(/*max=*/true); }
-
-  /// Finds minimum results of division
-  /// of the given arguments' minimum and maximum values.
-  /// Negative values may introduce sign cancellation.
-  ///
-  /// @returns Minimum value for division of arguments.
-  double Min() noexcept override { return GetExtremum(/*max=*/false); }
-
- private:
-  double GetSample() noexcept override;
-
-  /// @param[in] maximum  Flag to return maximum value.
-  ///
-  /// @returns One of extremums.
-  double GetExtremum(bool maximum) noexcept;
-};
+const char* const kUnitsToString[] = {"unitless", "bool",    "int",   "float",
+                                      "hours",    "hours-1", "years", "years-1",
+                                      "fit",      "demands"};
 
 }  // namespace mef
 }  // namespace scram
diff --git a/src/expression/arithmetic.cc b/src/expression/arithmetic.cc
new file mode 100644
index 0000000..ccb0022
--- /dev/null
+++ b/src/expression/arithmetic.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2014-2016 Olzhas Rakhimov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/// @file arithmetic.cc
+/// Implementation of various arithmetic expressions.
+
+#include "arithmetic.h"
+
+#include <algorithm>
+
+#include "src/error.h"
+
+namespace scram {
+namespace mef {
+
+Neg::Neg(const ExpressionPtr& expression)
+    : Expression({expression}),
+      expression_(*expression) {}
+
+BinaryExpression::BinaryExpression(std::vector<ExpressionPtr> args)
+    : Expression(std::move(args)) {
+  if (Expression::args().size() < 2)
+    throw InvalidArgument("Expression requires 2 or more arguments.");
+}
+
+double Mul::Mean() noexcept {
+  double mean = 1;
+  for (const ExpressionPtr& arg : Expression::args())
+    mean *= arg->Mean();
+  return mean;
+}
+
+double Mul::GetSample() noexcept {
+  double result = 1;
+  for (const ExpressionPtr& arg : Expression::args())
+    result *= arg->Sample();
+  return result;
+}
+
+double Mul::GetExtremum(bool maximum) noexcept {
+  double max_val = 1;  // Maximum possible product.
+  double min_val = 1;  // Minimum possible product.
+  for (const ExpressionPtr& arg : Expression::args()) {
+    double mult_max = arg->Max();
+    double mult_min = arg->Min();
+    double max_max = max_val * mult_max;
+    double max_min = max_val * mult_min;
+    double min_max = min_val * mult_max;
+    double min_min = min_val * mult_min;
+    max_val = std::max({max_max, max_min, min_max, min_min});
+    min_val = std::min({max_max, max_min, min_max, min_min});
+  }
+  return maximum ? max_val : min_val;
+}
+
+void Div::Validate() const {
+  auto it = Expression::args().begin();
+  for (++it; it != Expression::args().end(); ++it) {
+    const auto& expr = *it;
+    if (!expr->Mean() || !expr->Max() || !expr->Min())
+      throw InvalidArgument("Division by 0.");
+  }
+}
+
+double Div::Mean() noexcept {
+  auto it = Expression::args().begin();
+  double mean = (*it)->Mean();
+  for (++it; it != Expression::args().end(); ++it) {
+    mean /= (*it)->Mean();
+  }
+  return mean;
+}
+
+double Div::GetSample() noexcept {
+  auto it = Expression::args().begin();
+  double result = (*it)->Sample();
+  for (++it; it != Expression::args().end(); ++it)
+    result /= (*it)->Sample();
+  return result;
+}
+
+double Div::GetExtremum(bool maximum) noexcept {
+  auto it = Expression::args().begin();
+  double max_value = (*it)->Max();  // Maximum possible result.
+  double min_value = (*it)->Min();  // Minimum possible result.
+  for (++it; it != Expression::args().end(); ++it) {
+    double div_max = (*it)->Max();
+    double div_min = (*it)->Min();
+    double max_max = max_value / div_max;
+    double max_min = max_value / div_min;
+    double min_max = min_value / div_max;
+    double min_min = min_value / div_min;
+    max_value = std::max({max_max, max_min, min_max, min_min});
+    min_value = std::min({max_max, max_min, min_max, min_min});
+  }
+  return maximum ? max_value : min_value;
+}
+
+}  // namespace mef
+}  // namespace scram
diff --git a/src/expression/arithmetic.h b/src/expression/arithmetic.h
new file mode 100644
index 0000000..cd0e99c
--- /dev/null
+++ b/src/expression/arithmetic.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2014-2016 Olzhas Rakhimov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/// @file arithmetic.h
+/// A collection of arithmetic expressions.
+
+#ifndef SCRAM_SRC_EXPRESSION_ARITHMETIC_H_
+#define SCRAM_SRC_EXPRESSION_ARITHMETIC_H_
+
+#include <vector>
+
+#include "src/expression.h"
+
+namespace scram {
+namespace mef {
+
+/// This class for negation of numerical value or another expression.
+class Neg : public Expression {
+ public:
+  /// Construct a new expression
+  /// that negates a given argument expression.
+  ///
+  /// @param[in] expression  The expression to be negated.
+  explicit Neg(const ExpressionPtr& expression);
+
+  double Mean() noexcept override { return -expression_.Mean(); }
+  double Max() noexcept override { return -expression_.Min(); }
+  double Min() noexcept override { return -expression_.Max(); }
+
+ private:
+  double GetSample() noexcept override { return -expression_.Sample(); }
+
+  Expression& expression_;  ///< Expression that is used for negation.
+};
+
+/// Base class for expressions that require 2 or more arguments.
+class BinaryExpression : public Expression {
+ public:
+  /// Checks the number of provided arguments upon initialization.
+  ///
+  /// @param[in] args  Arguments of this expression.
+  ///
+  /// @throws InvalidArgument  The number of arguments is fewer than 2.
+  explicit BinaryExpression(std::vector<ExpressionPtr> args);
+};
+
+/// This expression adds all the given expressions' values.
+class Add : public BinaryExpression {
+ public:
+  using BinaryExpression::BinaryExpression;
+
+  double Mean() noexcept override { return Compute(&Expression::Mean); }
+  double Max() noexcept override { return Compute(&Expression::Max); }
+  double Min() noexcept override { return Compute(&Expression::Min); }
+
+ private:
+  double GetSample() noexcept override {
+    return Compute(&Expression::Sample);
+  }
+
+  /// Adds all argument expression values.
+  ///
+  /// @param[in] value  The getter function for the arg expression value.
+  ///
+  /// @returns The sum of the expression values.
+  double Compute(double (Expression::*value)()) {
+    double result = 0;
+    for (const ExpressionPtr& arg : Expression::args())
+      result += ((*arg).*value)();
+    return result;
+  }
+};
+
+/// This expression performs subtraction operation.
+/// First expression minus the rest of the given expressions' values.
+class Sub : public BinaryExpression {
+ public:
+  using BinaryExpression::BinaryExpression;
+
+  double Mean() noexcept override { return Compute(&Expression::Mean); }
+  double Max() noexcept override {
+    return Compute(&Expression::Max, &Expression::Min);
+  }
+  double Min() noexcept override {
+    return Compute(&Expression::Min, &Expression::Max);
+  }
+
+ private:
+  double GetSample() noexcept override {
+    return Compute(&Expression::Sample);
+  }
+
+  /// Performs the subtraction of all argument expression values.
+  ///
+  /// @param[in] first_value  The getter function for the first arg expression.
+  /// @param[in] rest_value  The getter function for the rest arg expressions.
+  ///                        If not given, it is equal to first_value.
+  ///
+  /// @returns first_value() - sum(rest_value()).
+  double Compute(double (Expression::*first_value)(),
+                 double (Expression::*rest_value)() = nullptr) {
+    if (!rest_value)
+      rest_value = first_value;
+
+    auto it = Expression::args().begin();
+    double result = ((**it).*first_value)();
+    for (++it; it != Expression::args().end(); ++it) {
+      result -= ((**it).*rest_value)();
+    }
+    return result;
+  }
+};
+
+/// This expression performs multiplication operation.
+class Mul : public BinaryExpression {
+ public:
+  using BinaryExpression::BinaryExpression;
+
+  double Mean() noexcept override;
+
+  /// Finds maximum product
+  /// from the given arguments' minimum and maximum values.
+  /// Negative values may introduce sign cancellation.
+  ///
+  /// @returns Maximum possible value of the product.
+  double Max() noexcept override { return GetExtremum(/*max=*/true); }
+
+  /// Finds minimum product
+  /// from the given arguments' minimum and maximum values.
+  /// Negative values may introduce sign cancellation.
+  ///
+  /// @returns Minimum possible value of the product.
+  double Min() noexcept override { return GetExtremum(/*max=*/false); }
+
+ private:
+  double GetSample() noexcept override;
+
+  /// @param[in] maximum  Flag to return maximum value.
+  ///
+  /// @returns One of extremums.
+  double GetExtremum(bool maximum) noexcept;
+};
+
+/// This expression performs division operation.
+/// The expression divides the first given argument by
+/// the rest of argument expressions.
+class Div : public BinaryExpression {
+ public:
+  using BinaryExpression::BinaryExpression;
+
+  /// @throws InvalidArgument  Division by 0.
+  void Validate() const override;
+
+  double Mean() noexcept override;
+
+  /// Finds maximum results of division
+  /// of the given arguments' minimum and maximum values.
+  /// Negative values may introduce sign cancellation.
+  ///
+  /// @returns Maximum value for division of arguments.
+  double Max() noexcept override { return GetExtremum(/*max=*/true); }
+
+  /// Finds minimum results of division
+  /// of the given arguments' minimum and maximum values.
+  /// Negative values may introduce sign cancellation.
+  ///
+  /// @returns Minimum value for division of arguments.
+  double Min() noexcept override { return GetExtremum(/*max=*/false); }
+
+ private:
+  double GetSample() noexcept override;
+
+  /// @param[in] maximum  Flag to return maximum value.
+  ///
+  /// @returns One of extremums.
+  double GetExtremum(bool maximum) noexcept;
+};
+
+}  // namespace mef
+}  // namespace scram
+
+#endif  // SCRAM_SRC_EXPRESSION_ARITHMETIC_H_
diff --git a/src/expression/constant.cc b/src/expression/constant.cc
new file mode 100644
index 0000000..7da0ed2
--- /dev/null
+++ b/src/expression/constant.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014-2016 Olzhas Rakhimov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/// @file constant.cc
+/// Implementation of various constant expressions.
+
+#include "constant.h"
+
+#include <boost/math/constants/constants.hpp>
+
+#include "src/error.h"
+
+namespace scram {
+namespace mef {
+
+const ExpressionPtr ConstantExpression::kOne(new ConstantExpression(1));
+const ExpressionPtr ConstantExpression::kZero(new ConstantExpression(0));
+const ExpressionPtr ConstantExpression::kPi(
+    new ConstantExpression(boost::math::constants::pi<double>()));
+
+ConstantExpression::ConstantExpression(double value)
+    : Expression({}),
+      value_(value) {}
+
+ConstantExpression::ConstantExpression(int value)
+    : ConstantExpression(static_cast<double>(value)) {}
+
+ConstantExpression::ConstantExpression(bool value)
+    : ConstantExpression(static_cast<double>(value)) {}
+
+MissionTime::MissionTime(double time, Units unit)
+    : ConstantExpression(time),
+      unit_(unit) {
+  if (time < 0)
+    throw LogicError("Mission time cannot be negative.");
+}
+
+}  // namespace mef
+}  // namespace scram
diff --git a/src/expression/constant.h b/src/expression/constant.h
new file mode 100644
index 0000000..58975a4
--- /dev/null
+++ b/src/expression/constant.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014-2016 Olzhas Rakhimov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/// @file constant.h
+/// Constant expressions that cannot have uncertainties.
+
+#ifndef SCRAM_SRC_EXPRESSION_CONSTANT_H_
+#define SCRAM_SRC_EXPRESSION_CONSTANT_H_
+
+#include "src/expression.h"
+
+namespace scram {
+namespace mef {
+
+/// Indicates a constant value.
+class ConstantExpression : public Expression {
+ public:
+  static const ExpressionPtr kOne;  ///< Constant 1 or True.
+  static const ExpressionPtr kZero;  ///< Constant 0 or False.
+  static const ExpressionPtr kPi;  ///< Constant PI value.
+
+  /// Constructor for numerical values.
+  ///
+  /// @param[in] value  Float numerical value.
+  explicit ConstantExpression(double value);
+
+  /// Constructor for numerical values.
+  ///
+  /// @param[in] value  Integer numerical value.
+  explicit ConstantExpression(int value);
+
+  /// Constructor for boolean values.
+  ///
+  /// @param[in] value  true for 1 and false for 0 value of this constant.
+  explicit ConstantExpression(bool value);
+
+  double Mean() noexcept override { return value_; }
+  bool IsConstant() noexcept override { return true; }
+
+ private:
+  double GetSample() noexcept override { return value_; }
+
+  const double value_;  ///< The universal value to represent int, bool, double.
+};
+
+/// The system mission time.
+class MissionTime : public ConstantExpression {
+ public:
+  /// Sets the mission time.
+  /// This function is expected to be used only once.
+  ///
+  /// @param[in] time  The mission time.
+  /// @param[in] unit  The unit of the given ``time`` argument.
+  ///
+  /// @throws LogicError  The time value is negative.
+  explicit MissionTime(double time, Units unit = kHours);
+
+  /// @returns The unit of the system mission time.
+  Units unit() const { return unit_; }
+
+ private:
+  Units unit_;  ///< Units of this parameter.
+};
+
+}  // namespace mef
+}  // namespace scram
+
+#endif  // SCRAM_SRC_EXPRESSION_CONSTANT_H_
diff --git a/src/expression/exponential.cc b/src/expression/exponential.cc
new file mode 100644
index 0000000..3ddf1dd
--- /dev/null
+++ b/src/expression/exponential.cc
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2014-2016 Olzhas Rakhimov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/// @file exponential.cc
+/// Implementation of various exponential expressions.
+
+#include "exponential.h"
+
+#include "src/error.h"
+
+namespace scram {
+namespace mef {
+
+ExponentialExpression::ExponentialExpression(const ExpressionPtr& lambda,
+                                             const ExpressionPtr& t)
+    : Expression({lambda, t}),
+      lambda_(*lambda),
+      time_(*t) {}
+
+void ExponentialExpression::Validate() const {
+  if (lambda_.Mean() < 0) {
+    throw InvalidArgument("The rate of failure cannot be negative.");
+  } else if (time_.Mean() < 0) {
+    throw InvalidArgument("The mission time cannot be negative.");
+  } else if (lambda_.Min() < 0) {
+    throw InvalidArgument("The sampled rate of failure cannot be negative.");
+  } else if (time_.Min() < 0) {
+    throw InvalidArgument("The sampled mission time cannot be negative.");
+  }
+}
+
+GlmExpression::GlmExpression(const ExpressionPtr& gamma,
+                             const ExpressionPtr& lambda,
+                             const ExpressionPtr& mu,
+                             const ExpressionPtr& t)
+    : Expression({gamma, lambda, mu, t}),
+      gamma_(*gamma),
+      lambda_(*lambda),
+      mu_(*mu),
+      time_(*t) {}
+
+void GlmExpression::Validate() const {
+  if (lambda_.Mean() < 0) {
+    throw InvalidArgument("The rate of failure cannot be negative.");
+  } else if (mu_.Mean() < 0) {
+    throw InvalidArgument("The rate of repair cannot be negative.");
+  } else if (gamma_.Mean() < 0 || gamma_.Mean() > 1) {
+    throw InvalidArgument("Invalid value for probability.");
+  } else if (time_.Mean() < 0) {
+    throw InvalidArgument("The mission time cannot be negative.");
+  } else if (lambda_.Min() < 0) {
+    throw InvalidArgument("The sampled rate of failure cannot be negative.");
+  } else if (mu_.Min() < 0) {
+    throw InvalidArgument("The sampled rate of repair cannot be negative.");
+  } else if (gamma_.Min() < 0 || gamma_.Max() > 1) {
+    throw InvalidArgument("Invalid sampled gamma value for probability.");
+  } else if (time_.Min() < 0) {
+    throw InvalidArgument("The sampled mission time cannot be negative.");
+  }
+}
+
+double GlmExpression::Mean() noexcept {
+  return Compute(gamma_.Mean(), lambda_.Mean(), mu_.Mean(), time_.Mean());
+}
+
+double GlmExpression::GetSample() noexcept {
+  return Compute(gamma_.Sample(), lambda_.Sample(), mu_.Sample(),
+                 time_.Sample());
+}
+
+double GlmExpression::Compute(double gamma, double lambda, double mu,
+                              double time) noexcept {
+  double r = lambda + mu;
+  return (lambda - (lambda - gamma * r) * std::exp(-r * time)) / r;
+}
+
+WeibullExpression::WeibullExpression(const ExpressionPtr& alpha,
+                                     const ExpressionPtr& beta,
+                                     const ExpressionPtr& t0,
+                                     const ExpressionPtr& time)
+    : Expression({alpha, beta, t0, time}),
+      alpha_(*alpha),
+      beta_(*beta),
+      t0_(*t0),
+      time_(*time) {}
+
+void WeibullExpression::Validate() const {
+  if (alpha_.Mean() <= 0) {
+    throw InvalidArgument("The scale parameter for Weibull distribution must"
+                          " be positive.");
+  } else if (beta_.Mean() <= 0) {
+    throw InvalidArgument("The shape parameter for Weibull distribution must"
+                          " be positive.");
+  } else if (t0_.Mean() < 0) {
+    throw InvalidArgument("Invalid value for time shift.");
+  } else if (time_.Mean() < 0) {
+    throw InvalidArgument("The mission time cannot be negative.");
+  } else if (time_.Mean() < t0_.Mean()) {
+    throw InvalidArgument("The mission time must be longer than time shift.");
+  } else if (alpha_.Min() <= 0) {
+    throw InvalidArgument("The scale parameter for Weibull distribution must"
+                          " be positive for sampled values.");
+  } else if (beta_.Min() <= 0) {
+    throw InvalidArgument("The shape parameter for Weibull distribution must"
+                          " be positive for sampled values.");
+  } else if (t0_.Min() < 0) {
+    throw InvalidArgument("Invalid value for time shift in sampled values.");
+  } else if (time_.Min() < 0) {
+    throw InvalidArgument("The sampled mission time cannot be negative.");
+  } else if (time_.Min() < t0_.Max()) {
+    throw InvalidArgument("The sampled mission time must be"
+                          " longer than time shift.");
+  }
+}
+
+double WeibullExpression::Compute(double alpha, double beta,
+                                  double t0, double time) noexcept {
+  return 1 - std::exp(-std::pow((time - t0) / alpha, beta));
+}
+
+}  // namespace mef
+}  // namespace scram
diff --git a/src/expression/exponential.h b/src/expression/exponential.h
new file mode 100644
index 0000000..81f974a
--- /dev/null
+++ b/src/expression/exponential.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2014-2016 Olzhas Rakhimov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/// @file exponential.h
+/// Expressions and distributions
+/// that are described with exponential formulas.
+
+#ifndef SCRAM_SRC_EXPRESSION_EXPONENTIAL_H_
+#define SCRAM_SRC_EXPRESSION_EXPONENTIAL_H_
+
+#include <cmath>
+
+#include "src/expression.h"
+
+namespace scram {
+namespace mef {
+
+/// Negative exponential distribution
+/// with hourly failure rate and time.
+class ExponentialExpression : public Expression {
+ public:
+  /// Constructor for exponential expression with two arguments.
+  ///
+  /// @param[in] lambda  Hourly rate of failure.
+  /// @param[in] t  Mission time in hours.
+  ExponentialExpression(const ExpressionPtr& lambda, const ExpressionPtr& t);
+
+  /// @throws InvalidArgument  The failure rate or time is negative.
+  void Validate() const override;
+
+  double Mean() noexcept override {
+    return 1 - std::exp(-(lambda_.Mean() * time_.Mean()));
+  }
+
+  double Max() noexcept override {
+    return 1 - std::exp(-(lambda_.Max() * time_.Max()));
+  }
+
+  double Min() noexcept override {
+    return 1 - std::exp(-(lambda_.Min() * time_.Min()));
+  }
+
+ private:
+  double GetSample() noexcept override {
+    return 1 - std::exp(-(lambda_.Sample() * time_.Sample()));
+  }
+
+  Expression& lambda_;  ///< Failure rate in hours.
+  Expression& time_;  ///< Mission time in hours.
+};
+
+/// Exponential with probability of failure on demand,
+/// hourly failure rate, hourly repairing rate, and time.
+///
+/// @todo Find the minimum and maximum values.
+class GlmExpression : public Expression {
+ public:
+  /// Constructor for GLM or exponential expression with four arguments.
+  ///
+  /// @param[in] gamma  Probability of failure on demand.
+  /// @param[in] lambda  Hourly rate of failure.
+  /// @param[in] mu  Hourly repairing rate.
+  /// @param[in] t  Mission time in hours.
+  GlmExpression(const ExpressionPtr& gamma, const ExpressionPtr& lambda,
+                const ExpressionPtr& mu, const ExpressionPtr& t);
+
+  void Validate() const override;
+
+  double Mean() noexcept override;
+  double Max() noexcept override { return 1; }
+  double Min() noexcept override { return 0; }
+
+ private:
+  double GetSample() noexcept override;
+
+  /// Computes the value for GLM expression.
+  ///
+  /// @param[in] gamma  Value for probability on demand.
+  /// @param[in] lambda  Value for hourly rate of failure.
+  /// @param[in] mu  Value for hourly repair rate.
+  /// @param[in] time  Mission time in hours.
+  ///
+  /// @returns Probability of failure on demand.
+  double Compute(double gamma, double lambda, double mu, double time) noexcept;
+
+  Expression& gamma_;  ///< Probability of failure on demand.
+  Expression& lambda_;  ///< Failure rate in hours.
+  Expression& mu_;  ///< Repair rate in hours.
+  Expression& time_;  ///< Mission time in hours.
+};
+
+/// Weibull distribution with scale, shape, time shift, and time.
+class WeibullExpression : public Expression {
+ public:
+  /// Constructor for Weibull distribution.
+  ///
+  /// @param[in] alpha  Scale parameter.
+  /// @param[in] beta  Shape parameter.
+  /// @param[in] t0  Time shift.
+  /// @param[in] time  Mission time.
+  WeibullExpression(const ExpressionPtr& alpha, const ExpressionPtr& beta,
+                    const ExpressionPtr& t0, const ExpressionPtr& time);
+
+  void Validate() const override;
+
+  double Mean() noexcept override {
+    return Compute(alpha_.Mean(), beta_.Mean(), t0_.Mean(), time_.Mean());
+  }
+
+  double Max() noexcept override {
+    return Compute(alpha_.Min(), beta_.Max(), t0_.Min(), time_.Max());
+  }
+
+  double Min() noexcept override {
+    return Compute(alpha_.Max(), beta_.Min(), t0_.Max(), time_.Min());
+  }
+
+ private:
+  double GetSample() noexcept override {
+    return Compute(alpha_.Sample(), beta_.Sample(), t0_.Sample(),
+                   time_.Sample());
+  }
+
+  /// Calculates Weibull expression.
+  ///
+  /// @param[in] alpha  Scale parameter.
+  /// @param[in] beta  Shape parameter.
+  /// @param[in] t0  Time shift.
+  /// @param[in] time  Mission time.
+  ///
+  /// @returns Calculated value.
+  double Compute(double alpha, double beta, double t0, double time) noexcept;
+
+  Expression& alpha_;  ///< Scale parameter.
+  Expression& beta_;  ///< Shape parameter.
+  Expression& t0_;  ///< Time shift in hours.
+  Expression& time_;  ///< Mission time in hours.
+};
+
+}  // namespace mef
+}  // namespace scram
+
+#endif  // SCRAM_SRC_EXPRESSION_EXPONENTIAL_H_
diff --git a/src/expression.cc b/src/expression/random_deviate.cc
similarity index 50%
copy from src/expression.cc
copy to src/expression/random_deviate.cc
index daa3bf2..57f3925 100644
--- a/src/expression.cc
+++ b/src/expression/random_deviate.cc
@@ -15,196 +15,23 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/// @file expression.cc
-/// Implementation of various expressions
-/// for basic event probability description.
+/// @file random_deviate.cc
+/// Implementations of random deviate expressions.
 
-#include "expression.h"
+#include "random_deviate.h"
 
-#include <algorithm>
+#include <cmath>
 
-#include <boost/math/constants/constants.hpp>
-#include <boost/range/algorithm.hpp>
+#include <boost/math/special_functions/beta.hpp>
+#include <boost/math/special_functions/erf.hpp>
+#include <boost/math/special_functions/gamma.hpp>
 
-#include "error.h"
-#include "ext.h"
-#include "random.h"
+#include "src/error.h"
+#include "src/random.h"
 
 namespace scram {
 namespace mef {
 
-Expression::Expression(std::vector<ExpressionPtr> args)
-    : args_(std::move(args)),
-      sampled_value_(0),
-      sampled_(false) {}
-
-double Expression::Sample() noexcept {
-  if (!sampled_) {
-    sampled_ = true;
-    sampled_value_ = this->GetSample();
-  }
-  return sampled_value_;
-}
-
-void Expression::Reset() noexcept {
-  if (!sampled_)
-    return;
-  sampled_ = false;
-  for (const ExpressionPtr& arg : args_)
-    arg->Reset();
-}
-
-bool Expression::IsConstant() noexcept {
-  return ext::all_of(
-      args_, [](const ExpressionPtr& arg) { return arg->IsConstant(); });
-}
-
-Parameter::Parameter(std::string name, std::string base_path,
-                     RoleSpecifier role)
-    : Expression({}),
-      Element(std::move(name)),
-      Role(role, std::move(base_path)),
-      Id(*this, *this),
-      unit_(kUnitless),
-      unused_(true),
-      expression_(nullptr) {}
-
-void Parameter::expression(const ExpressionPtr& expression) {
-  if (expression_)
-    throw LogicError("Parameter expression is already set.");
-  expression_ = expression.get();
-  Expression::AddArg(expression);
-}
-
-MissionTime::MissionTime()
-    : Expression({}),
-      mission_time_(-1),
-      unit_(kHours) {}
-
-const ExpressionPtr ConstantExpression::kOne(new ConstantExpression(1));
-const ExpressionPtr ConstantExpression::kZero(new ConstantExpression(0));
-const ExpressionPtr ConstantExpression::kPi(
-    new ConstantExpression(boost::math::constants::pi<double>()));
-
-ConstantExpression::ConstantExpression(double val)
-    : Expression({}),
-      value_(val) {}
-
-ConstantExpression::ConstantExpression(int val)
-    : Expression({}),
-      value_(val) {}
-
-ConstantExpression::ConstantExpression(bool val)
-    : Expression({}),
-      value_(val) {}
-
-ExponentialExpression::ExponentialExpression(const ExpressionPtr& lambda,
-                                             const ExpressionPtr& t)
-    : Expression({lambda, t}),
-      lambda_(*lambda),
-      time_(*t) {}
-
-void ExponentialExpression::Validate() const {
-  if (lambda_.Mean() < 0) {
-    throw InvalidArgument("The rate of failure cannot be negative.");
-  } else if (time_.Mean() < 0) {
-    throw InvalidArgument("The mission time cannot be negative.");
-  } else if (lambda_.Min() < 0) {
-    throw InvalidArgument("The sampled rate of failure cannot be negative.");
-  } else if (time_.Min() < 0) {
-    throw InvalidArgument("The sampled mission time cannot be negative.");
-  }
-}
-
-GlmExpression::GlmExpression(const ExpressionPtr& gamma,
-                             const ExpressionPtr& lambda,
-                             const ExpressionPtr& mu,
-                             const ExpressionPtr& t)
-    : Expression({gamma, lambda, mu, t}),
-      gamma_(*gamma),
-      lambda_(*lambda),
-      mu_(*mu),
-      time_(*t) {}
-
-void GlmExpression::Validate() const {
-  if (lambda_.Mean() < 0) {
-    throw InvalidArgument("The rate of failure cannot be negative.");
-  } else if (mu_.Mean() < 0) {
-    throw InvalidArgument("The rate of repair cannot be negative.");
-  } else if (gamma_.Mean() < 0 || gamma_.Mean() > 1) {
-    throw InvalidArgument("Invalid value for probability.");
-  } else if (time_.Mean() < 0) {
-    throw InvalidArgument("The mission time cannot be negative.");
-  } else if (lambda_.Min() < 0) {
-    throw InvalidArgument("The sampled rate of failure cannot be negative.");
-  } else if (mu_.Min() < 0) {
-    throw InvalidArgument("The sampled rate of repair cannot be negative.");
-  } else if (gamma_.Min() < 0 || gamma_.Max() > 1) {
-    throw InvalidArgument("Invalid sampled gamma value for probability.");
-  } else if (time_.Min() < 0) {
-    throw InvalidArgument("The sampled mission time cannot be negative.");
-  }
-}
-
-double GlmExpression::Mean() noexcept {
-  return Compute(gamma_.Mean(), lambda_.Mean(), mu_.Mean(), time_.Mean());
-}
-
-double GlmExpression::GetSample() noexcept {
-  return Compute(gamma_.Sample(), lambda_.Sample(), mu_.Sample(),
-                 time_.Sample());
-}
-
-double GlmExpression::Compute(double gamma, double lambda, double mu,
-                              double time) noexcept {
-  double r = lambda + mu;
-  return (lambda - (lambda - gamma * r) * std::exp(-r * time)) / r;
-}
-
-WeibullExpression::WeibullExpression(const ExpressionPtr& alpha,
-                                     const ExpressionPtr& beta,
-                                     const ExpressionPtr& t0,
-                                     const ExpressionPtr& time)
-    : Expression({alpha, beta, t0, time}),
-      alpha_(*alpha),
-      beta_(*beta),
-      t0_(*t0),
-      time_(*time) {}
-
-void WeibullExpression::Validate() const {
-  if (alpha_.Mean() <= 0) {
-    throw InvalidArgument("The scale parameter for Weibull distribution must"
-                          " be positive.");
-  } else if (beta_.Mean() <= 0) {
-    throw InvalidArgument("The shape parameter for Weibull distribution must"
-                          " be positive.");
-  } else if (t0_.Mean() < 0) {
-    throw InvalidArgument("Invalid value for time shift.");
-  } else if (time_.Mean() < 0) {
-    throw InvalidArgument("The mission time cannot be negative.");
-  } else if (time_.Mean() < t0_.Mean()) {
-    throw InvalidArgument("The mission time must be longer than time shift.");
-  } else if (alpha_.Min() <= 0) {
-    throw InvalidArgument("The scale parameter for Weibull distribution must"
-                          " be positive for sampled values.");
-  } else if (beta_.Min() <= 0) {
-    throw InvalidArgument("The shape parameter for Weibull distribution must"
-                          " be positive for sampled values.");
-  } else if (t0_.Min() < 0) {
-    throw InvalidArgument("Invalid value for time shift in sampled values.");
-  } else if (time_.Min() < 0) {
-    throw InvalidArgument("The sampled mission time cannot be negative.");
-  } else if (time_.Min() < t0_.Max()) {
-    throw InvalidArgument("The sampled mission time must be"
-                          " longer than time shift.");
-  }
-}
-
-double WeibullExpression::Compute(double alpha, double beta,
-                                  double t0, double time) noexcept {
-  return 1 - std::exp(-std::pow((time - t0) / alpha, beta));
-}
-
 UniformDeviate::UniformDeviate(const ExpressionPtr& min,
                                const ExpressionPtr& max)
     : RandomDeviate({min, max}),
@@ -281,14 +108,12 @@ double LogNormalDeviate::GetSample() noexcept {
 double LogNormalDeviate::Max() noexcept {
   double sigma = ComputeScale(level_.Mean(), ef_.Mean());
   double mu = ComputeLocation(mean_.Max(), sigma);
-  return std::exp(
-      std::sqrt(2) * std::pow(boost::math::erfc(1 / 50), -1) * sigma + mu);
+  return std::exp(3 * sigma + mu);
 }
 
 double LogNormalDeviate::ComputeScale(double level, double ef) noexcept {
-  double p = level + (1 - level) / 2;
-  double z = std::sqrt(2) * boost::math::erfc_inv(2 * p);
-  return std::log(ef) / std::abs(z);
+  double z = -std::sqrt(2) * boost::math::erfc_inv(2 * level);
+  return std::log(ef) / z;
 }
 
 double LogNormalDeviate::ComputeLocation(double mean, double sigma) noexcept {
@@ -316,6 +141,12 @@ void GammaDeviate::Validate() const {
   }
 }
 
+double GammaDeviate::Max() noexcept {
+  using boost::math::gamma_q;
+  double k_max = k_.Max();
+  return theta_.Max() * std::pow(gamma_q(k_max, gamma_q(k_max, 0) - 0.99), -1);
+}
+
 double GammaDeviate::GetSample() noexcept {
   return Random::GammaGenerator(k_.Sample(), theta_.Sample());
 }
@@ -341,6 +172,10 @@ void BetaDeviate::Validate() const {
   }
 }
 
+double BetaDeviate::Max() noexcept {
+  return std::pow(boost::math::ibeta(alpha_.Max(), beta_.Max(), 0.99), -1);
+}
+
 double BetaDeviate::GetSample() noexcept {
   return Random::BetaGenerator(alpha_.Sample(), beta_.Sample());
 }
@@ -445,88 +280,5 @@ void Histogram::CheckWeights() const {
   }
 }
 
-Neg::Neg(const ExpressionPtr& expression)
-    : Expression({expression}),
-      expression_(*expression) {}
-
-BinaryExpression::BinaryExpression(std::vector<ExpressionPtr> args)
-    : Expression(std::move(args)) {
-  if (Expression::args().size() < 2)
-    throw InvalidArgument("Expression requires 2 or more arguments.");
-}
-
-double Mul::Mean() noexcept {
-  double mean = 1;
-  for (const ExpressionPtr& arg : Expression::args())
-    mean *= arg->Mean();
-  return mean;
-}
-
-double Mul::GetSample() noexcept {
-  double result = 1;
-  for (const ExpressionPtr& arg : Expression::args())
-    result *= arg->Sample();
-  return result;
-}
-
-double Mul::GetExtremum(bool maximum) noexcept {
-  double max_val = 1;  // Maximum possible product.
-  double min_val = 1;  // Minimum possible product.
-  for (const ExpressionPtr& arg : Expression::args()) {
-    double mult_max = arg->Max();
-    double mult_min = arg->Min();
-    double max_max = max_val * mult_max;
-    double max_min = max_val * mult_min;
-    double min_max = min_val * mult_max;
-    double min_min = min_val * mult_min;
-    max_val = std::max({max_max, max_min, min_max, min_min});
-    min_val = std::min({max_max, max_min, min_max, min_min});
-  }
-  return maximum ? max_val : min_val;
-}
-
-void Div::Validate() const {
-  auto it = Expression::args().begin();
-  for (++it; it != Expression::args().end(); ++it) {
-    const auto& expr = *it;
-    if (!expr->Mean() || !expr->Max() || !expr->Min())
-      throw InvalidArgument("Division by 0.");
-  }
-}
-
-double Div::Mean() noexcept {
-  auto it = Expression::args().begin();
-  double mean = (*it)->Mean();
-  for (++it; it != Expression::args().end(); ++it) {
-    mean /= (*it)->Mean();
-  }
-  return mean;
-}
-
-double Div::GetSample() noexcept {
-  auto it = Expression::args().begin();
-  double result = (*it)->Sample();
-  for (++it; it != Expression::args().end(); ++it)
-    result /= (*it)->Sample();
-  return result;
-}
-
-double Div::GetExtremum(bool maximum) noexcept {
-  auto it = Expression::args().begin();
-  double max_value = (*it)->Max();  // Maximum possible result.
-  double min_value = (*it)->Min();  // Minimum possible result.
-  for (++it; it != Expression::args().end(); ++it) {
-    double div_max = (*it)->Max();
-    double div_min = (*it)->Min();
-    double max_max = max_value / div_max;
-    double max_min = max_value / div_min;
-    double min_max = min_value / div_max;
-    double min_min = min_value / div_min;
-    max_value = std::max({max_max, max_min, min_max, min_min});
-    min_value = std::min({max_max, max_min, min_max, min_min});
-  }
-  return maximum ? max_value : min_value;
-}
-
 }  // namespace mef
 }  // namespace scram
diff --git a/src/expression/random_deviate.h b/src/expression/random_deviate.h
new file mode 100644
index 0000000..2dfc2fc
--- /dev/null
+++ b/src/expression/random_deviate.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2014-2016 Olzhas Rakhimov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/// @file random_deviate.h
+/// A collection of deviate expressions with random distributions
+/// sampled at run-time.
+
+#ifndef SCRAM_SRC_EXPRESSION_RANDOM_DEVIATE_H_
+#define SCRAM_SRC_EXPRESSION_RANDOM_DEVIATE_H_
+
+#include <utility>
+#include <vector>
+
+#include "src/expression.h"
+
+namespace scram {
+namespace mef {
+
+/// Abstract base class for all deviate expressions.
+/// These expressions provide quantification for uncertainty and sensitivity.
+class RandomDeviate : public Expression {
+ public:
+  using Expression::Expression;
+
+  bool IsConstant() noexcept override { return false; }
+};
+
+/// Uniform distribution.
+class UniformDeviate : public RandomDeviate {
+ public:
+  /// Setup for uniform distribution.
+  ///
+  /// @param[in] min  Minimum value of the distribution.
+  /// @param[in] max  Maximum value of the distribution.
+  UniformDeviate(const ExpressionPtr& min, const ExpressionPtr& max);
+
+  /// @throws InvalidArgument  The min value is more or equal to max value.
+  void Validate() const override;
+
+  double Mean() noexcept override { return (min_.Mean() + max_.Mean()) / 2; }
+  double Max() noexcept override { return max_.Max(); }
+  double Min() noexcept override { return min_.Min(); }
+
+ private:
+  double GetSample() noexcept override;
+
+  Expression& min_;  ///< Minimum value of the distribution.
+  Expression& max_;  ///< Maximum value of the distribution.
+};
+
+/// Normal distribution.
+class NormalDeviate : public RandomDeviate {
+ public:
+  /// Setup for normal distribution.
+  ///
+  /// @param[in] mean  The mean of the distribution.
+  /// @param[in] sigma  The standard deviation of the distribution.
+  NormalDeviate(const ExpressionPtr& mean, const ExpressionPtr& sigma);
+
+  /// @throws InvalidArgument  The sigma is negative or zero.
+  void Validate() const override;
+
+  double Mean() noexcept override { return mean_.Mean(); }
+
+  /// @returns ~99.9% percentile value.
+  ///
+  /// @warning This is only an approximation of the maximum value.
+  double Max() noexcept override { return mean_.Max() + 6 * sigma_.Max(); }
+
+  /// @returns Less than 0.1% percentile value.
+  ///
+  /// @warning This is only an approximation.
+  double Min() noexcept override { return mean_.Min() - 6 * sigma_.Max(); }
+
+ private:
+  double GetSample() noexcept override;
+
+  Expression& mean_;  ///< Mean value of normal distribution.
+  Expression& sigma_;  ///< Standard deviation of normal distribution.
+};
+
+/// Log-normal distribution defined by
+/// its expected value and error factor of certain confidence level.
+class LogNormalDeviate : public RandomDeviate {
+ public:
+  /// Setup for log-normal distribution.
+  ///
+  /// @param[in] mean  The mean of the log-normal distribution
+  ///                  not the mean of underlying normal distribution,
+  ///                  which is parameter mu.
+  ///                  mu is the location parameter,
+  ///                  sigma is the scale factor.
+  ///                  E(x) = exp(mu + sigma^2 / 2)
+  /// @param[in] ef  The error factor of the log-normal distribution.
+  ///                EF = exp(z_alpha * sigma)
+  /// @param[in] level  The confidence level.
+  LogNormalDeviate(const ExpressionPtr& mean, const ExpressionPtr& ef,
+                   const ExpressionPtr& level);
+
+  /// @throws InvalidArgument  (mean <= 0) or (ef <= 0) or invalid level
+  void Validate() const override;
+
+  double Mean() noexcept override { return mean_.Mean(); }
+
+  /// 99.9 percentile estimate.
+  double Max() noexcept override;
+
+  double Min() noexcept override { return 0; }
+
+ private:
+  double GetSample() noexcept override;
+
+  /// Computes the scale parameter of the distribution.
+  ///
+  /// @param[in] level  The confidence level.
+  /// @param[in] ef  The error factor of the log-normal distribution.
+  ///
+  /// @returns Scale parameter (sigma) value.
+  double ComputeScale(double level, double ef) noexcept;
+
+  /// Computes the location parameter of the distribution.
+  ///
+  /// @param[in] mean  The mean of the log-normal distribution.
+  /// @param[in] sigma  The scale parameter of the distribution.
+  ///
+  /// @returns Value of location parameter (mu) value.
+  double ComputeLocation(double mean, double sigma) noexcept;
+
+  Expression& mean_;  ///< Mean value of the log-normal distribution.
+  Expression& ef_;  ///< Error factor of the log-normal distribution.
+  Expression& level_;  ///< Confidence level of the log-normal distribution.
+};
+
+/// Gamma distribution.
+class GammaDeviate : public RandomDeviate {
+ public:
+  /// Setup for Gamma distribution.
+  ///
+  /// @param[in] k  Shape parameter of Gamma distribution.
+  /// @param[in] theta  Scale parameter of Gamma distribution.
+  GammaDeviate(const ExpressionPtr& k, const ExpressionPtr& theta);
+
+  /// @throws InvalidArgument  (k <= 0) or (theta <= 0)
+  void Validate() const override;
+
+  double Mean() noexcept override { return k_.Mean() * theta_.Mean(); }
+
+  /// @returns 99 percentile.
+  double Max() noexcept override;
+
+  double Min() noexcept override { return 0; }
+
+ private:
+  double GetSample() noexcept override;
+
+  Expression& k_;  ///< The shape parameter of the gamma distribution.
+  Expression& theta_;  ///< The scale factor of the gamma distribution.
+};
+
+/// Beta distribution.
+class BetaDeviate : public RandomDeviate {
+ public:
+  /// Setup for Beta distribution.
+  ///
+  /// @param[in] alpha  Alpha shape parameter of Gamma distribution.
+  /// @param[in] beta  Beta shape parameter of Gamma distribution.
+  BetaDeviate(const ExpressionPtr& alpha, const ExpressionPtr& beta);
+
+  /// @throws InvalidArgument  (alpha <= 0) or (beta <= 0)
+  void Validate() const override;
+
+  double Mean() noexcept override {
+    double alpha_mean = alpha_.Mean();
+    return alpha_mean / (alpha_mean + beta_.Mean());
+  }
+
+  /// @returns 99 percentile.
+  double Max() noexcept override;
+
+  double Min() noexcept override { return 0; }
+
+ private:
+  double GetSample() noexcept override;
+
+  Expression& alpha_;  ///< The alpha shape parameter.
+  Expression& beta_;  ///< The beta shape parameter.
+};
+
+/// Histogram distribution.
+class Histogram : public RandomDeviate {
+ public:
+  /// Histogram distribution setup.
+  ///
+  /// @param[in] boundaries  The bounds of intervals.
+  /// @param[in] weights  The positive weights of intervals
+  ///                     restricted by the upper boundaries.
+  ///                     Therefore, the number of weights must be
+  ///                     equal to the number of intervals.
+  ///
+  /// @throws InvalidArgument  The boundaries container size is not equal to
+  ///                          weights container size + 1.
+  ///
+  /// @note This description of histogram sampling is mostly for probabilities.
+  ///       Therefore, it is not flexible.
+  ///       Currently, it allows sampling both boundaries and weights.
+  ///       This behavior makes checking
+  ///       for valid arrangement of the boundaries mandatory
+  ///       for each sampling.
+  ///       Moreover, the first starting point is assumed but not defined.
+  ///       The starting point is assumed to be 0,
+  ///       which leaves only positive values for boundaries.
+  ///       This behavior is restrictive
+  ///       and should be handled accordingly.
+  Histogram(std::vector<ExpressionPtr> boundaries,
+            std::vector<ExpressionPtr> weights);
+
+  /// @throws InvalidArgument  The boundaries are not strictly increasing,
+  ///                          or weights are negative.
+  void Validate() const override {
+    CheckBoundaries();
+    CheckWeights();
+  }
+
+  double Mean() noexcept override;
+  double Max() noexcept override {
+    return (*std::prev(boundaries_.second))->Max();
+  }
+  double Min() noexcept override { return 0; }
+
+ private:
+  /// Access to args.
+  using Iterator = std::vector<ExpressionPtr>::const_iterator;
+
+  double GetSample() noexcept override;
+
+  /// Checks if values of boundary expressions are strictly increasing.
+  ///
+  /// @throws InvalidArgument  The mean values are not strictly increasing.
+  void CheckBoundaries() const;
+
+  /// Checks if values of weights are non-negative.
+  ///
+  /// @throws InvalidArgument  The mean values are negative.
+  void CheckWeights() const;
+
+  std::pair<Iterator, Iterator> boundaries_;  ///< Boundaries of the intervals.
+  std::pair<Iterator, Iterator> weights_;  ///< Weights of the intervals.
+};
+
+}  // namespace mef
+}  // namespace scram
+
+#endif  // SCRAM_SRC_EXPRESSION_RANDOM_DEVIATE_H_
diff --git a/src/ext.h b/src/ext.h
index 65f5047..e428313 100644
--- a/src/ext.h
+++ b/src/ext.h
@@ -23,7 +23,6 @@
 
 #include <algorithm>
 #include <memory>
-#include <type_traits>
 
 #include <boost/range/algorithm/find_if.hpp>
 
@@ -143,6 +142,18 @@ bool all_of(const SinglePassRange& rng, UnaryPredicate pred) {
 }
 /// @}
 
+/// Passes an unmanaged resource to a smart pointer
+/// with automatic type deduction.
+/// This is a helper function to avoid boilerplate code.
+/// This helper would be unnecessary
+/// if template arguments could be deduced from constructors.
+///
+/// @param[in] dumb_handle  A raw pointer to the resource.
+///
+/// @returns A smart pointer exclusively owning the resource.
+template <typename T>
+auto make_unique(T* dumb_handle) { return std::unique_ptr<T>(dumb_handle); }
+
 }  // namespace ext
 
 #endif  // SCRAM_SRC_EXT_H_
diff --git a/src/fault_tree.cc b/src/fault_tree.cc
index 25102be..88e1ef4 100644
--- a/src/fault_tree.cc
+++ b/src/fault_tree.cc
@@ -20,9 +20,6 @@
 
 #include "fault_tree.h"
 
-#include <utility>
-
-#include "cycle.h"
 #include "error.h"
 
 namespace scram {
diff --git a/src/fault_tree.h b/src/fault_tree.h
index a0d50a1..817174e 100644
--- a/src/fault_tree.h
+++ b/src/fault_tree.h
@@ -31,7 +31,7 @@
 #include "ccf_group.h"
 #include "element.h"
 #include "event.h"
-#include "expression.h"
+#include "parameter.h"
 
 namespace scram {
 namespace mef {
diff --git a/src/fault_tree_analysis.cc b/src/fault_tree_analysis.cc
index b7f2fa8..97106e8 100644
--- a/src/fault_tree_analysis.cc
+++ b/src/fault_tree_analysis.cc
@@ -21,11 +21,14 @@
 #include "fault_tree_analysis.h"
 
 #include <algorithm>
+#include <iostream>
 #include <utility>
 
 #include <boost/container/flat_set.hpp>
 #include <boost/range/algorithm.hpp>
 
+#include "event.h"
+
 namespace scram {
 namespace core {
 
diff --git a/src/fault_tree_analysis.h b/src/fault_tree_analysis.h
index 0b93604..adfcd44 100644
--- a/src/fault_tree_analysis.h
+++ b/src/fault_tree_analysis.h
@@ -31,12 +31,17 @@
 
 #include "analysis.h"
 #include "boolean_graph.h"
-#include "event.h"
 #include "logger.h"
 #include "preprocessor.h"
 #include "settings.h"
 
 namespace scram {
+
+namespace mef {  // Decouple from the analysis code.
+class Gate;
+class BasicEvent;
+}  // namespace mef
+
 namespace core {
 
 /// Event or its complement
diff --git a/src/importance_analysis.cc b/src/importance_analysis.cc
index c60e1d5..77a88e1 100644
--- a/src/importance_analysis.cc
+++ b/src/importance_analysis.cc
@@ -24,6 +24,7 @@
 #include <algorithm>
 #include <unordered_set>
 
+#include "event.h"
 #include "logger.h"
 
 namespace scram {
diff --git a/src/importance_analysis.h b/src/importance_analysis.h
index cb62ba8..3572fc7 100644
--- a/src/importance_analysis.h
+++ b/src/importance_analysis.h
@@ -28,11 +28,15 @@
 #include <vector>
 
 #include "bdd.h"
-#include "event.h"
 #include "probability_analysis.h"
 #include "settings.h"
 
 namespace scram {
+
+namespace mef {  // Decouple from the analysis code header.
+class BasicEvent;
+}  // namespace mef
+
 namespace core {
 
 /// Collection of importance factors for variables.
@@ -126,11 +130,6 @@ class ImportanceAnalyzerBase : public ImportanceAnalysis {
   /// to calculate the total and conditional probabilities for factors.
   ///
   /// @param[in] prob_analyzer  Instantiated probability analyzer.
-  ///
-  /// @pre Probability analyzer can work with modified probability values.
-  ///
-  /// @post Probability analyzer's probability values are
-  ///       reset to the original values (event probabilities).
   explicit ImportanceAnalyzerBase(
       ProbabilityAnalyzer<Calculator>* prob_analyzer)
       : ImportanceAnalysis(prob_analyzer),
@@ -167,32 +166,35 @@ class ImportanceAnalyzerBase : public ImportanceAnalysis {
 template <class Calculator>
 class ImportanceAnalyzer : public ImportanceAnalyzerBase<Calculator> {
  public:
-  using ImportanceAnalyzerBase<Calculator>::ImportanceAnalyzerBase;
+  /// @copydoc ImportanceAnalyzerBase<Calculator>::ImportanceAnalyzerBase
+  explicit ImportanceAnalyzer(ProbabilityAnalyzer<Calculator>* prob_analyzer)
+      : ImportanceAnalyzerBase<Calculator>(prob_analyzer),
+        p_vars_(prob_analyzer->p_vars()) {}
 
  private:
   double CalculateMif(int index) noexcept override;
+  std::vector<double> p_vars_;  ///< A private copy of variable probabilities.
 };
 
 template <class Calculator>
 double ImportanceAnalyzer<Calculator>::CalculateMif(int index) noexcept {
   using Base = ImportanceAnalyzerBase<Calculator>;
-  std::vector<double>& p_vars = Base::prob_analyzer()->p_vars();
+
+  double p_store = p_vars_[index];  // Save the original value for restoring.
+
   // Calculate P(top/event)
-  p_vars[index] = 1;
-  double p_e = Base::prob_analyzer()->CalculateTotalProbability();
-  assert(p_e >= 0);
-  if (p_e > 1)
-    p_e = 1;
+  p_vars_[index] = 1;
+  double p_e = Base::prob_analyzer()->CalculateTotalProbability(p_vars_);
+  assert(p_e >= 0 && p_e <= 1);
 
   // Calculate P(top/Not event)
-  p_vars[index] = 0;
-  double p_not_e = Base::prob_analyzer()->CalculateTotalProbability();
-  assert(p_not_e >= 0);
-  if (p_not_e > 1)
-    p_not_e = 1;
-
-  // Restore the probability.
-  p_vars[index] = Base::prob_analyzer()->graph()->GetBasicEvent(index)->p();
+  p_vars_[index] = 0;
+  double p_not_e = Base::prob_analyzer()->CalculateTotalProbability(p_vars_);
+  assert(p_not_e >= 0 && p_not_e <= 1);
+
+  // Restore the probability for next importance calculation.
+  p_vars_[index] = p_store;
+
   return p_e - p_not_e;
 }
 
diff --git a/src/initializer.cc b/src/initializer.cc
index 34153f0..fd0081c 100644
--- a/src/initializer.cc
+++ b/src/initializer.cc
@@ -28,6 +28,9 @@
 #include "cycle.h"
 #include "env.h"
 #include "error.h"
+#include "expression/arithmetic.h"
+#include "expression/exponential.h"
+#include "expression/random_deviate.h"
 #include "logger.h"
 #include "xml.h"
 
@@ -62,8 +65,7 @@ RoleSpecifier GetRole(const std::string& s, RoleSpecifier parent_role) {
 Initializer::Initializer(const std::vector<std::string>& xml_files,
                          core::Settings settings)
     : settings_(std::move(settings)),
-      mission_time_(std::make_shared<MissionTime>()) {
-  mission_time_->mission_time(settings_.mission_time());
+      mission_time_(std::make_shared<MissionTime>(settings_.mission_time())) {
   try {
     ProcessInputFiles(xml_files);
   } catch (const CycleError&) {
@@ -368,7 +370,8 @@ FormulaPtr Initializer::GetFormula(const xmlpp::Element* formula_node,
     type = "null";
   }
 
-  int pos = boost::find(kOperatorToString, type) - kOperatorToString.begin();
+  int pos =
+      boost::find(kOperatorToString, type) - std::begin(kOperatorToString);
   assert(pos < kNumOperators && "Unexpected operator type.");
 
   FormulaPtr formula(new Formula(static_cast<Operator>(pos)));
@@ -533,7 +536,7 @@ ParameterPtr Initializer::RegisterParameter(const xmlpp::Element* param_node,
   // Attach units.
   std::string unit = GetAttributeValue(param_node, "unit");
   if (!unit.empty()) {
-    int pos = boost::find(kUnitsToString, unit) - kUnitsToString.begin();
+    int pos = boost::find(kUnitsToString, unit) - std::begin(kUnitsToString);
     assert(pos < kNumUnits && "Unexpected unit kind.");
     parameter->unit(static_cast<Units>(pos));
   }
diff --git a/src/initializer.h b/src/initializer.h
index d18f7c3..6f15306 100644
--- a/src/initializer.h
+++ b/src/initializer.h
@@ -34,8 +34,10 @@
 #include "element.h"
 #include "event.h"
 #include "expression.h"
+#include "expression/constant.h"
 #include "fault_tree.h"
 #include "model.h"
+#include "parameter.h"
 #include "settings.h"
 
 namespace scram {
@@ -133,7 +135,7 @@ class Initializer : private boost::noncopyable {
 
   /// Attaches attributes and a label to the elements of the analysis.
   /// These attributes are not XML attributes
-  /// but OpenPSA format defined arbitrary attributes
+  /// but the Open-PSA format defined arbitrary attributes
   /// and a label that can be attached to many analysis elements.
   ///
   /// @param[in] element_node  XML element.
diff --git a/src/logger.cc b/src/logger.cc
index 8828171..250a561 100644
--- a/src/logger.cc
+++ b/src/logger.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2015 Olzhas Rakhimov
+ * Copyright (C) 2014-2016 Olzhas Rakhimov
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,6 +20,8 @@
 
 #include "logger.h"
 
+#include <cstdio>
+
 #include <string>
 
 #include "error.h"
@@ -31,11 +33,26 @@ const char* const Logger::kLevelToString_[] = {"ERROR", "WARNING", "INFO",
                                                "DEBUG4", "DEBUG5"};
 LogLevel Logger::report_level_ = ERROR;
 
+Logger::~Logger() noexcept {
+  os_ << std::endl;
+  // fprintf used for thread safety.
+  std::fprintf(stderr, "%s", os_.str().c_str());
+  std::fflush(stderr);
+}
+
 void Logger::SetVerbosity(int level) {
-  if (level < 0 || level > kMaxVerbosity)
+  if (level < 0 || level > kMaxVerbosity) {
     throw InvalidArgument("Log verbosity must be between 0 and " +
                           std::to_string(kMaxVerbosity));
+  }
   report_level_ = static_cast<LogLevel>(level);
 }
 
+std::ostringstream& Logger::Get(LogLevel level) {
+  os_ << Logger::kLevelToString_[level] << ": ";
+  if (level >= DEBUG1)
+    os_ << std::string(level - DEBUG1 + 1, '\t');
+  return os_;
+}
+
 }  // namespace scram
diff --git a/src/logger.h b/src/logger.h
index 1da2858..e274cef 100644
--- a/src/logger.h
+++ b/src/logger.h
@@ -30,11 +30,9 @@
 #define SCRAM_SRC_LOGGER_H_
 
 #include <cstdint>
-#include <cstdio>
 
 #include <chrono>
 #include <sstream>
-#include <string>
 
 #include <boost/noncopyable.hpp>
 
@@ -96,12 +94,7 @@ const int kMaxVerbosity = 7;  ///< The index of the last level.
 class Logger : private boost::noncopyable {
  public:
   /// Flashes all the logs into the standard error upon destruction.
-  ~Logger() noexcept {
-    os_ << std::endl;
-    // fprintf used for thread safety.
-    std::fprintf(stderr, "%s", os_.str().c_str());
-    std::fflush(stderr);
-  }
+  ~Logger() noexcept;
 
   /// @returns Reference to the cut-off level for reporting.
   static LogLevel report_level() { return report_level_; }
@@ -124,19 +117,16 @@ class Logger : private boost::noncopyable {
   /// @param[in] level  The log level for the information.
   ///
   /// @returns Formatted output stringstream with the log level information.
-  std::ostringstream& Get(LogLevel level) {
-    os_ << Logger::kLevelToString_[level] << ": ";
-    os_ << std::string(level < DEBUG1 ? 0 : level - DEBUG1 + 1, '\t');
-    return os_;
-  }
+  std::ostringstream& Get(LogLevel level);
 
  private:
   /// Translates the logging level into a string.
   /// The index is the value of the enum.
   static const char* const kLevelToString_[];
 
-  std::ostringstream os_;  ///< Main stringstream to gather the logs.
   static LogLevel report_level_;  ///< Cut-off log level for reporting.
+
+  std::ostringstream os_;  ///< Main stringstream to gather the logs.
 };
 
 }  // namespace scram
diff --git a/src/model.cc b/src/model.cc
index d1e4c60..820e98f 100644
--- a/src/model.cc
+++ b/src/model.cc
@@ -20,6 +20,8 @@
 
 #include "model.h"
 
+#include "ext.h"
+
 namespace scram {
 namespace mef {
 
@@ -68,6 +70,49 @@ void Model::AddCcfGroup(const CcfGroupPtr& ccf_group) {
   }
 }
 
+ParameterPtr Model::GetParameter(const std::string& entity_reference,
+                                 const std::string& base_path) {
+  return GetEntity(entity_reference, base_path, parameters_);
+}
+
+HouseEventPtr Model::GetHouseEvent(const std::string& entity_reference,
+                                   const std::string& base_path) {
+  return GetEntity(entity_reference, base_path, house_events_);
+}
+
+BasicEventPtr Model::GetBasicEvent(const std::string& entity_reference,
+                                   const std::string& base_path) {
+  return GetEntity(entity_reference, base_path, basic_events_);
+}
+
+GatePtr Model::GetGate(const std::string& entity_reference,
+                       const std::string& base_path) {
+  return GetEntity(entity_reference, base_path, gates_);
+}
+
+template <class T>
+std::shared_ptr<T> Model::GetEntity(const std::string& entity_reference,
+                                    const std::string& base_path,
+                                    const LookupTable<T>& container) {
+  assert(!entity_reference.empty());
+  if (!base_path.empty()) {  // Check the local scope.
+    if (auto it = ext::find(container.entities_by_path,
+                            base_path + "." + entity_reference))
+      return *it;
+  }
+
+  auto at = [&entity_reference](const auto& reference_container) {
+    if (auto it = ext::find(reference_container, entity_reference))
+      return *it;
+    throw std::out_of_range("The event cannot be found.");
+  };
+
+  if (entity_reference.find('.') == std::string::npos)  // Public entity.
+    return at(container.entities_by_id);
+
+  return at(container.entities_by_path);  // Direct access.
+}
+
 /// Helper macro for Model::BindEvent event discovery.
 #define BIND_EVENT(access, path_reference)                       \
   if (auto it = ext::find(gates_.access, path_reference))        \
diff --git a/src/model.h b/src/model.h
index f6eff84..4e89120 100644
--- a/src/model.h
+++ b/src/model.h
@@ -34,9 +34,8 @@
 #include "ccf_group.h"
 #include "element.h"
 #include "event.h"
-#include "ext.h"
-#include "expression.h"
 #include "fault_tree.h"
+#include "parameter.h"
 
 namespace scram {
 namespace mef {
@@ -122,21 +121,13 @@ class Model : public Element, boost::noncopyable {
   /// @throws std::out_of_range  The entity cannot be found.
   /// @{
   ParameterPtr GetParameter(const std::string& entity_reference,
-                            const std::string& base_path) {
-    return GetEntity(entity_reference, base_path, parameters_);
-  }
+                            const std::string& base_path);
   HouseEventPtr GetHouseEvent(const std::string& entity_reference,
-                              const std::string& base_path) {
-    return GetEntity(entity_reference, base_path, house_events_);
-  }
+                              const std::string& base_path);
   BasicEventPtr GetBasicEvent(const std::string& entity_reference,
-                              const std::string& base_path) {
-    return GetEntity(entity_reference, base_path, basic_events_);
-  }
+                              const std::string& base_path);
   GatePtr GetGate(const std::string& entity_reference,
-                  const std::string& base_path) {
-    return GetEntity(entity_reference, base_path, gates_);
-  }
+                  const std::string& base_path);
   /// @}
 
   /// Binds a formula with its argument event.
@@ -202,25 +193,7 @@ class Model : public Element, boost::noncopyable {
   template <class T>
   std::shared_ptr<T> GetEntity(const std::string& entity_reference,
                                const std::string& base_path,
-                               const LookupTable<T>& container) {
-    assert(!entity_reference.empty());
-    if (!base_path.empty()) {  // Check the local scope.
-      if (auto it = ext::find(container.entities_by_path,
-                              base_path + "." + entity_reference))
-        return *it;
-    }
-
-    auto at = [&entity_reference](const auto& reference_container) {
-      if (auto it = ext::find(reference_container, entity_reference))
-        return *it;
-      throw std::out_of_range("The event cannot be found.");
-    };
-
-    if (entity_reference.find('.') == std::string::npos)  // Public entity.
-      return at(container.entities_by_id);
-
-    return at(container.entities_by_path);  // Direct access.
-  }
+                               const LookupTable<T>& container);
 
   /// A collection of defined constructs in the model.
   /// @{
diff --git a/src/logger.cc b/src/parameter.cc
similarity index 51%
copy from src/logger.cc
copy to src/parameter.cc
index 8828171..6754f81 100644
--- a/src/logger.cc
+++ b/src/parameter.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2015 Olzhas Rakhimov
+ * Copyright (C) 2014-2016 Olzhas Rakhimov
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -15,27 +15,32 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/// @file logger.cc
-/// Initializing static members of Logger class.
+/// @file parameter.cc
+/// Implementation of expression parameters.
 
-#include "logger.h"
-
-#include <string>
+#include "parameter.h"
 
 #include "error.h"
 
 namespace scram {
-
-const char* const Logger::kLevelToString_[] = {"ERROR", "WARNING", "INFO",
-                                               "DEBUG1", "DEBUG2", "DEBUG3",
-                                               "DEBUG4", "DEBUG5"};
-LogLevel Logger::report_level_ = ERROR;
-
-void Logger::SetVerbosity(int level) {
-  if (level < 0 || level > kMaxVerbosity)
-    throw InvalidArgument("Log verbosity must be between 0 and " +
-                          std::to_string(kMaxVerbosity));
-  report_level_ = static_cast<LogLevel>(level);
+namespace mef {
+
+Parameter::Parameter(std::string name, std::string base_path,
+                     RoleSpecifier role)
+    : Expression({}),
+      Element(std::move(name)),
+      Role(role, std::move(base_path)),
+      Id(*this, *this),
+      unit_(kUnitless),
+      unused_(true),
+      expression_(nullptr) {}
+
+void Parameter::expression(const ExpressionPtr& expression) {
+  if (expression_)
+    throw LogicError("Parameter expression is already set.");
+  expression_ = expression.get();
+  Expression::AddArg(expression);
 }
 
+}  // namespace mef
 }  // namespace scram
diff --git a/src/parameter.h b/src/parameter.h
new file mode 100644
index 0000000..fbfd1a2
--- /dev/null
+++ b/src/parameter.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2014-2016 Olzhas Rakhimov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/// @file parameter.h
+/// Parameter expressions that act like a shareable variable.
+
+#ifndef SCRAM_SRC_PARAMETER_H_
+#define SCRAM_SRC_PARAMETER_H_
+
+#include <memory>
+#include <string>
+
+#include "element.h"
+#include "expression.h"
+
+namespace scram {
+namespace mef {
+
+/// This class provides a representation of a variable
+/// in basic event description.
+/// It is both expression and element description.
+class Parameter : public Expression,
+                  public Element,
+                  public Role,
+                  public Id,
+                  public NodeMark {
+ public:
+  /// Creates a parameter as a variable for future references.
+  ///
+  /// @param[in] name  The name of this variable (Case sensitive).
+  /// @param[in] base_path  The series of containers to get this parameter.
+  /// @param[in] role  The role of the parameter within the model or container.
+  ///
+  /// @throws LogicError  The name is empty.
+  /// @throws InvalidArgument  The name or reference paths are malformed.
+  explicit Parameter(std::string name, std::string base_path = "",
+                     RoleSpecifier role = RoleSpecifier::kPublic);
+
+  /// Sets the expression of this parameter.
+  ///
+  /// @param[in] expression  The expression to describe this parameter.
+  ///
+  /// @throws LogicError  The parameter expression is already set.
+  void expression(const ExpressionPtr& expression);
+
+  /// @returns The unit of this parameter.
+  Units unit() const { return unit_; }
+
+  /// Sets the unit of this parameter.
+  ///
+  /// @param[in] unit  A valid unit.
+  void unit(Units unit) { unit_ = unit; }
+
+  /// @returns The usage state of this parameter.
+  bool unused() { return unused_; }
+
+  /// Sets the usage state for this parameter.
+  ///
+  /// @param[in] state  The usage state for this parameter.
+  void unused(bool state) { unused_ = state; }
+
+  double Mean() noexcept override { return expression_->Mean(); }
+  double Max() noexcept override { return expression_->Max(); }
+  double Min() noexcept override { return expression_->Min(); }
+
+ private:
+  double GetSample() noexcept override { return expression_->Sample(); }
+
+  Units unit_;  ///< Units of this parameter.
+  bool unused_;  ///< Usage state.
+  Expression* expression_;  ///< Expression for this parameter.
+};
+
+using ParameterPtr = std::shared_ptr<Parameter>;  ///< Shared parameters.
+
+}  // namespace mef
+}  // namespace scram
+
+#endif  // SCRAM_SRC_PARAMETER_H_
diff --git a/src/preprocessor.cc b/src/preprocessor.cc
index e2a734c..f901b25 100644
--- a/src/preprocessor.cc
+++ b/src/preprocessor.cc
@@ -78,6 +78,7 @@
 #include <queue>
 #include <unordered_set>
 
+#include <boost/functional/hash.hpp>
 #include <boost/math/special_functions/sign.hpp>
 #include <boost/range/algorithm.hpp>
 #include <boost/range/algorithm_ext.hpp>
@@ -117,6 +118,64 @@ void Preprocessor::Run() noexcept {
   }
 }
 
+/// Container of unique gates.
+/// This container acts like an unordered set of gates.
+/// The gates are equivalent
+/// if they have the same semantics.
+/// However, this set does not test
+/// for the isomorphism of the gates' Boolean formulas.
+class Preprocessor::GateSet {
+ public:
+  /// Inserts a gate into the set
+  /// if it is semantically unique.
+  ///
+  /// @param[in] gate  The gate to insert.
+  ///
+  /// @returns A pair of the unique gate and
+  ///          the insertion success flag.
+  std::pair<GatePtr, bool> insert(const GatePtr& gate) noexcept {
+    auto result = table_[gate->type()].insert(gate);
+    return {*result.first, result.second};
+  }
+
+ private:
+  /// Functor for hashing gates by their arguments.
+  ///
+  /// @note The hashing discards the logic of the gate.
+  struct Hash {
+    /// Operator overload for hashing.
+    ///
+    /// @param[in] gate  The gate which hash must be calculated.
+    ///
+    /// @returns Hash value of the gate
+    ///          from its arguments but not logic.
+    std::size_t operator()(const GatePtr& gate) const noexcept {
+      return boost::hash_range(gate->args().begin(), gate->args().end());
+    }
+  };
+  /// Functor for equality test for gates by their arguments.
+  ///
+  /// @note The equality discards the logic of the gate.
+  struct Equal {
+    /// Operator overload for gate argument equality test.
+    ///
+    /// @param[in] lhs  The first gate.
+    /// @param[in] rhs  The second gate.
+    ///
+    /// @returns true if the gate arguments are equal.
+    bool operator()(const GatePtr& lhs, const GatePtr& rhs) const noexcept {
+      assert(lhs->type() == rhs->type());
+      if (lhs->args() != rhs->args())
+        return false;
+      if (lhs->type() == kVote && lhs->vote_number() != rhs->vote_number())
+        return false;
+      return true;
+    }
+  };
+  /// Container of gates grouped by their types.
+  std::array<std::unordered_set<GatePtr, Hash, Equal>, kNumOperators> table_;
+};
+
 namespace {  // Boolean graph structure verification tools.
 
 /// Functor to sanity check the marks of Boolean graph gates.
diff --git a/src/preprocessor.h b/src/preprocessor.h
index 95e0bd1..dfcf8f7 100644
--- a/src/preprocessor.h
+++ b/src/preprocessor.h
@@ -64,6 +64,8 @@ class Preprocessor : private boost::noncopyable {
   virtual void Run() noexcept = 0;
 
  protected:
+  class GateSet;  ///< Container of unique gates by semantics.
+
   /// The initial phase of preprocessing.
   /// The most basic cleanup algorithms are applied.
   /// The cleanup should benefit all other phases
diff --git a/src/probability_analysis.cc b/src/probability_analysis.cc
index 99c16c7..ea7e63f 100644
--- a/src/probability_analysis.cc
+++ b/src/probability_analysis.cc
@@ -21,6 +21,10 @@
 
 #include "probability_analysis.h"
 
+#include "event.h"
+#include "logger.h"
+#include "settings.h"
+
 namespace scram {
 namespace core {
 
@@ -65,7 +69,7 @@ double RareEventCalculator::Calculate(
     assert(!cut_set.empty() && "Detected an empty cut set.");
     sum += CutSetProbabilityCalculator::Calculate(cut_set, p_vars);
   }
-  return sum;
+  return sum > 1 ? 1 : sum;
 }
 
 double McubCalculator::Calculate(
@@ -81,6 +85,13 @@ double McubCalculator::Calculate(
   return 1 - m;
 }
 
+void ProbabilityAnalyzerBase::ExtractVariableProbabilities() {
+  p_vars_.push_back(-1);  // Padding.
+  for (const mef::BasicEvent* event : graph_->basic_events()) {
+    p_vars_.push_back(event->p());
+  }
+}
+
 ProbabilityAnalyzer<Bdd>::ProbabilityAnalyzer(FaultTreeAnalyzer<Bdd>* fta)
     : ProbabilityAnalyzerBase(fta),
       owner_(false) {
@@ -95,22 +106,28 @@ ProbabilityAnalyzer<Bdd>::~ProbabilityAnalyzer() noexcept {
     delete bdd_graph_;
 }
 
-double ProbabilityAnalyzer<Bdd>::CalculateTotalProbability() noexcept {
+double ProbabilityAnalyzer<Bdd>::CalculateTotalProbability(
+    const std::vector<double>& p_vars) noexcept {
   CLOCK(calc_time);  // BDD based calculation time.
   LOG(DEBUG4) << "Calculating probability with BDD...";
   current_mark_ = !current_mark_;
-  double prob = CalculateProbability(bdd_graph_->root().vertex, current_mark_);
+  double prob =
+      CalculateProbability(bdd_graph_->root().vertex, current_mark_, p_vars);
   if (bdd_graph_->root().complement)
     prob = 1 - prob;
   LOG(DEBUG4) << "Calculated probability " << prob << " in " << DUR(calc_time);
   return prob;
 }
 
-void ProbabilityAnalyzer<Bdd>::CreateBdd(const mef::Gate& root) noexcept {
+void ProbabilityAnalyzer<Bdd>::CreateBdd(
+    const FaultTreeAnalysis& fta) noexcept {
+  CLOCK(total_time);
+
   CLOCK(ft_creation);
   BooleanGraph* bool_graph =
-      new BooleanGraph(root, Analysis::settings().ccf_analysis());
+      new BooleanGraph(fta.top_event(), Analysis::settings().ccf_analysis());
   LOG(DEBUG2) << "Boolean graph is created in " << DUR(ft_creation);
+
   CLOCK(prep_time);  // Overall preprocessing time.
   LOG(DEBUG2) << "Preprocessing...";
   Preprocessor* preprocessor = new CustomPreprocessor<Bdd>(bool_graph);
@@ -123,11 +140,14 @@ void ProbabilityAnalyzer<Bdd>::CreateBdd(const mef::Gate& root) noexcept {
   bdd_graph_ = new Bdd(bool_graph, Analysis::settings());
   LOG(DEBUG2) << "BDD is created in " << DUR(bdd_time);
   delete bool_graph;  // The original graph of FTA is usable with the BDD.
+
+  Analysis::AddAnalysisTime(DUR(total_time));
 }
 
 double ProbabilityAnalyzer<Bdd>::CalculateProbability(
     const Bdd::VertexPtr& vertex,
-    bool mark) noexcept {
+    bool mark,
+    const std::vector<double>& p_vars) noexcept {
   if (vertex->terminal())
     return 1;
   ItePtr ite = Ite::Ptr(vertex);
@@ -137,14 +157,14 @@ double ProbabilityAnalyzer<Bdd>::CalculateProbability(
   double p_var = 0;
   if (ite->module()) {
     const Bdd::Function& res = bdd_graph_->modules().find(ite->index())->second;
-    p_var = CalculateProbability(res.vertex, mark);
+    p_var = CalculateProbability(res.vertex, mark, p_vars);
     if (res.complement)
       p_var = 1 - p_var;
   } else {
-    p_var = ProbabilityAnalyzerBase::p_vars()[ite->index()];
+    p_var = p_vars[ite->index()];
   }
-  double high = CalculateProbability(ite->high(), mark);
-  double low = CalculateProbability(ite->low(), mark);
+  double high = CalculateProbability(ite->high(), mark, p_vars);
+  double low = CalculateProbability(ite->low(), mark, p_vars);
   if (ite->complement_edge())
     low = 1 - low;
   ite->p(p_var * high + (1 - p_var) * low);
diff --git a/src/probability_analysis.h b/src/probability_analysis.h
index ff7373d..2f6510a 100644
--- a/src/probability_analysis.h
+++ b/src/probability_analysis.h
@@ -26,10 +26,7 @@
 #include "analysis.h"
 #include "bdd.h"
 #include "boolean_graph.h"
-#include "event.h"
 #include "fault_tree_analysis.h"
-#include "logger.h"
-#include "settings.h"
 
 namespace scram {
 namespace core {
@@ -114,10 +111,10 @@ class RareEventCalculator : private CutSetProbabilityCalculator {
   ///
   /// @pre Absolute indices of events directly map to vector indices.
   ///
-  /// @post The returned probability value may not be acceptable.
-  ///       That is, it may be out of the acceptable [0, 1] range.
-  ///       The caller of this function must decide
-  ///       what to do in this case.
+  /// @post In case the calculated probability exceeds 1,
+  ///       the probability is adjusted to 1.
+  ///       It is very unwise to use the rare-event approximation
+  ///       with large probability values.
   double Calculate(const std::vector<CutSet>& cut_sets,
                    const std::vector<double>& p_vars) noexcept;
 };
@@ -148,7 +145,12 @@ class ProbabilityAnalyzerBase : public ProbabilityAnalysis {
   ///
   /// @param[in] fta  Finished fault tree analyzer with results.
   template <class Algorithm>
-  explicit ProbabilityAnalyzerBase(const FaultTreeAnalyzer<Algorithm>* fta);
+  explicit ProbabilityAnalyzerBase(const FaultTreeAnalyzer<Algorithm>* fta)
+      : ProbabilityAnalysis(fta),
+        graph_(fta->graph()),
+        products_(fta->algorithm()->products()) {
+    ExtractVariableProbabilities();
+  }
 
   /// @returns The original Boolean graph from the fault tree analyzer.
   const BooleanGraph* graph() const { return graph_; }
@@ -156,38 +158,28 @@ class ProbabilityAnalyzerBase : public ProbabilityAnalysis {
   /// @returns The resulting products of the fault tree analyzer.
   const std::vector<Product>& products() const { return products_; }
 
-  /// @returns A modifiable mapping for probability values and indices.
-  ///
-  /// @pre Quantitative analyzers aware of how Probability analyzer works.
-  /// @pre Quantitative analyzers will cleanup after themselves.
-  ///
-  /// @warning This is a hack
-  ///          due to tight coupling of Quantitative analyzers.
-  ///
-  /// @todo Redesign the use and manipulation of variable probabilities.
-  std::vector<double>& p_vars() { return p_vars_; }
+  /// @returns A mapping for probability values and indices.
+  const std::vector<double>& p_vars() const { return p_vars_; }
 
  protected:
   ~ProbabilityAnalyzerBase() = default;
 
  private:
+  /// Upon construction of the probability analysis,
+  /// stores the variable probabilities in a continuous container
+  /// for retrieval by their indices instead of pointers.
+  ///
+  /// @note This function may seem redundant,
+  ///       for it's super-short and simple to do it inline in the constructor.
+  ///       The main benefit of the out-of-line implementation
+  ///       is compile-time decoupling from the input BasicEvent classes.
+  void ExtractVariableProbabilities();
+
   const BooleanGraph* graph_;  ///< Boolean graph from the fault tree analysis.
   const std::vector<Product>& products_;  ///< A collection of products.
   std::vector<double> p_vars_;  ///< Variable probabilities.
 };
 
-template <class Algorithm>
-ProbabilityAnalyzerBase::ProbabilityAnalyzerBase(
-    const FaultTreeAnalyzer<Algorithm>* fta)
-    : ProbabilityAnalysis(fta),
-      graph_(fta->graph()),
-      products_(fta->algorithm()->products()) {
-  p_vars_.push_back(-1);  // Padding.
-  for (const mef::BasicEvent* event : graph_->basic_events()) {
-    p_vars_.push_back(event->p());
-  }
-}
-
 /// Fault-tree-analysis-aware probability analyzer.
 /// Probability analyzer provides the main engine for probability analysis.
 ///
@@ -197,15 +189,27 @@ class ProbabilityAnalyzer : public ProbabilityAnalyzerBase {
  public:
   using ProbabilityAnalyzerBase::ProbabilityAnalyzerBase;
 
+  /// Calculates the total probability
+  /// with a different set of probability values
+  /// than the one given upon construction.
+  ///
+  /// @param[in] p_vars  A map of probabilities of the graph variables.
+  ///                    The indices of the variables must map
+  ///                    exactly to the vector indices.
+  ///
+  /// @returns The total probability calculated with the given values.
+  double CalculateTotalProbability(const std::vector<double>& p_vars) noexcept {
+    return calc_.Calculate(ProbabilityAnalyzerBase::products(), p_vars);
+  }
+
+ private:
   /// Calculates the total probability.
   ///
   /// @returns The total probability of the graph or the sum of products.
   double CalculateTotalProbability() noexcept override {
-    return calc_.Calculate(ProbabilityAnalyzerBase::products(),
-                           ProbabilityAnalyzerBase::p_vars());
+    return CalculateTotalProbability(ProbabilityAnalyzerBase::p_vars());
   }
 
- private:
   Calculator calc_;  ///< Provider of the calculation logic.
 };
 
@@ -221,7 +225,12 @@ class ProbabilityAnalyzer<Bdd> : public ProbabilityAnalyzerBase {
   ///
   /// @param[in] fta  Finished fault tree analyzer with results.
   template <class Algorithm>
-  explicit ProbabilityAnalyzer(const FaultTreeAnalyzer<Algorithm>* fta);
+  explicit ProbabilityAnalyzer(const FaultTreeAnalyzer<Algorithm>* fta)
+      : ProbabilityAnalyzerBase(fta),
+        current_mark_(false),
+        owner_(true) {
+    CreateBdd(*fta);
+  }
 
   /// Reuses BDD structures from Fault tree analyzer.
   ///
@@ -240,47 +249,44 @@ class ProbabilityAnalyzer<Bdd> : public ProbabilityAnalyzerBase {
   /// @returns Binary decision diagram used for calculations.
   Bdd* bdd_graph() { return bdd_graph_; }
 
+  /// @copydoc ProbabilityAnalyzer::CalculateTotalProbability
+  double CalculateTotalProbability(const std::vector<double>& p_vars) noexcept;
+
+ private:
   /// Calculates the total probability.
   ///
   /// @returns The total probability of the graph.
-  double CalculateTotalProbability() noexcept override;
+  double CalculateTotalProbability() noexcept override {
+    return CalculateTotalProbability(ProbabilityAnalyzerBase::p_vars());
+  }
 
- private:
   /// Creates a new BDD for use by the analyzer.
   ///
-  /// @param[in] root  The root gate of the fault tree.
+  /// @param[in] fta  The fault tree analysis providing the root gate.
   ///
   /// @pre The function is called in the constructor only once.
-  void CreateBdd(const mef::Gate& root) noexcept;
+  void CreateBdd(const FaultTreeAnalysis& fta) noexcept;
 
   /// Calculates exact probability
   /// of a function graph represented by its root BDD vertex.
   ///
   /// @param[in] vertex  The root vertex of a function graph.
   /// @param[in] mark  A flag to mark traversed vertices.
+  /// @param[in] p_vars  The probabilities of the variables
+  ///                    mapped by their indices.
   ///
   /// @returns Probability value.
   ///
   /// @warning If a vertex is already marked with the input mark,
   ///          it will not be traversed and updated with a probability value.
-  double CalculateProbability(const Bdd::VertexPtr& vertex, bool mark) noexcept;
+  double CalculateProbability(const Bdd::VertexPtr& vertex, bool mark,
+                              const std::vector<double>& p_vars) noexcept;
 
   Bdd* bdd_graph_;  ///< The main BDD graph for analysis.
   bool current_mark_;  ///< To keep track of BDD current mark.
   bool owner_;  ///< Indication that pointers are handles.
 };
 
-template <class Algorithm>
-ProbabilityAnalyzer<Bdd>::ProbabilityAnalyzer(
-    const FaultTreeAnalyzer<Algorithm>* fta)
-    : ProbabilityAnalyzerBase(fta),
-      current_mark_(false),
-      owner_(true) {
-  CLOCK(main_time);
-  CreateBdd(fta->top_event());
-  Analysis::AddAnalysisTime(DUR(main_time));
-}
-
 }  // namespace core
 }  // namespace scram
 
diff --git a/src/random.h b/src/random.h
index 178676c..457d3f9 100644
--- a/src/random.h
+++ b/src/random.h
@@ -24,9 +24,10 @@
 #include <cassert>
 #include <cmath>
 
-#include <array>
 #include <random>
-#include <vector>
+
+#include <boost/random/beta_distribution.hpp>
+#include <boost/random/triangle_distribution.hpp>
 
 namespace scram {
 
@@ -36,6 +37,9 @@ namespace scram {
 /// In other words, the user should make sure
 /// that the passed parameters are valid.
 /// For example, standard deviation cannot be negative.
+///
+/// This facility wraps the engine and distributions.
+/// It provides convenience and reproducibility for the whole analysis.
 class Random {
  public:
   /// Sets the seed of the underlying random number generator.
@@ -45,16 +49,15 @@ class Random {
     Random::rng_.seed(static_cast<unsigned>(seed));
   }
 
-  /// RNG from uniform distribution.
+  /// RNG from a uniform distribution.
   ///
-  /// @param[in] min  Lower bound.
-  /// @param[in] max  Upper bound.
+  /// @param[in] lower  Lower bound.
+  /// @param[in] upper  Upper bound.
   ///
   /// @returns A sampled value.
-  static double UniformRealGenerator(double min, double max) noexcept {
-    assert(min < max);
-    std::uniform_real_distribution<double> dist(min, max);
-    return dist(rng_);
+  static double UniformRealGenerator(double lower, double upper) noexcept {
+    assert(lower < upper);
+    return std::uniform_real_distribution<>(lower, upper)(rng_);
   }
 
   /// RNG from a triangular distribution.
@@ -68,31 +71,29 @@ class Random {
                                     double upper) noexcept {
     assert(lower < mode);
     assert(mode < upper);
-    static const std::array<double, 3> weights = {0, 1, 0};
-    std::array<double, 3> intervals = {lower, mode, upper};
-    std::piecewise_linear_distribution<double> dist(intervals.begin(),
-                                                    intervals.end(),
-                                                    weights.begin());
-    return dist(rng_);
+    return boost::random::triangle_distribution<>(lower, mode, upper)(rng_);
   }
 
   /// RNG from a piecewise linear distribution.
   ///
-  /// @param[in] intervals  Interval points for the distribution.
-  ///                       The values must be strictly increasing.
-  /// @param[in] weights  Weights at the boundaries.
-  ///                     The number of weights must be equal to
-  ///                     the number of intervals (points - 1).
-  ///                     Extra weights are ignored.
+  /// @tparam IteratorB  Input iterator of interval boundaries returning double.
+  /// @tparam IteratorW  Input iterator of weights returning double.
+  ///
+  /// @param[in] first_b  The begin of the interval boundaries.
+  /// @param[in] last_b  The sentinel end of the interval boundaries.
+  /// @param[in] first_w  The begin of the interval weights.
   ///
   /// @returns A sampled value.
-  static double PiecewiseLinearGenerator(
-      const std::vector<double>& intervals,
-      const std::vector<double>& weights) noexcept {
-    std::piecewise_linear_distribution<double> dist(intervals.begin(),
-                                                    intervals.end(),
-                                                    weights.begin());
-    return dist(rng_);
+  ///
+  /// @pre Interval points for the distribution must be strictly increasing.
+  ///
+  /// @pre The number of weights must be equal to
+  ///      the number of intervals (boundaries - 1).
+  ///      Extra weights are ignored.
+  template <class IteratorB, class IteratorW>
+  static double PiecewiseLinearGenerator(IteratorB first_b, IteratorB last_b,
+                                         IteratorW first_w) noexcept {
+    return std::piecewise_linear_distribution<>(first_b, last_b, first_w)(rng_);
   }
 
   /// RNG from a histogram distribution.
@@ -114,35 +115,31 @@ class Random {
   template <class IteratorB, class IteratorW>
   static double HistogramGenerator(IteratorB first_b, IteratorB last_b,
                                    IteratorW first_w) noexcept {
-    std::piecewise_constant_distribution<double> dist(first_b, last_b, first_w);
+    std::piecewise_constant_distribution<> dist(first_b, last_b, first_w);
     return dist(rng_);
   }
 
   /// RNG from a discrete distribution.
   ///
-  /// @tparam T  Type of discrete values.
+  /// @tparam Iterator  Input iterator of weights returning double.
   ///
-  /// @param[in] values  Discrete values.
-  /// @param[in] weights  Weights for the corresponding values.
-  ///                     The size must be the same as the values vector size.
+  /// @param[in] first1  The begin of the interval weights.
+  /// @param[in] last1  The sentinel end of the interval weights.
   ///
-  /// @returns A sample Value from the value vector.
-  template <typename T>
-  static T DiscreteGenerator(const std::vector<T>& values,
-                             const std::vector<double>& weights) noexcept {
-    assert(values.size() == weights.size());
-    return values[DiscreteGenerator(weights)];
+  /// @returns Integer in the range [0, n).
+  template <class Iterator>
+  static int DiscreteGenerator(Iterator first1, Iterator last1) noexcept {
+    return std::discrete_distribution<>(first1, last1)(rng_);
   }
 
-  /// RNG from Binomial distribution.
+  /// RNG from a Binomial distribution.
   ///
   /// @param[in] n  Number of trials.
   /// @param[in] p  Probability of success.
   ///
   /// @returns The number of successes.
   static int BinomialGenerator(int n, double p) noexcept {
-    std::binomial_distribution<int> dist(n, p);
-    return dist(rng_);
+    return std::binomial_distribution<>(n, p)(rng_);
   }
 
   /// RNG from a normal distribution.
@@ -153,11 +150,10 @@ class Random {
   /// @returns A sampled value.
   static double NormalGenerator(double mean, double sigma) noexcept {
     assert(sigma >= 0);
-    std::normal_distribution<double> dist(mean, sigma);
-    return dist(rng_);
+    return std::normal_distribution<>(mean, sigma)(rng_);
   }
 
-  /// RNG from lognormal distribution.
+  /// RNG from a lognormal distribution.
   ///
   /// @param[in] m  The m location parameter of the distribution.
   /// @param[in] s  The s scale factor of the distribution.
@@ -165,11 +161,10 @@ class Random {
   /// @returns A sampled value.
   static double LogNormalGenerator(double m, double s) noexcept {
     assert(s >= 0);
-    std::lognormal_distribution<double> dist(m, s);
-    return dist(rng_);
+    return std::lognormal_distribution<>(m, s)(rng_);
   }
 
-  /// RNG from Gamma distribution.
+  /// RNG from a Gamma distribution.
   ///
   /// @param[in] k  Shape parameter of Gamma distribution.
   /// @param[in] theta  Scale parameter of Gamma distribution.
@@ -182,11 +177,10 @@ class Random {
   static double GammaGenerator(double k, double theta) noexcept {
     assert(k > 0);
     assert(theta > 0);
-    std::gamma_distribution<double> gamma_dist(k);
-    return theta * gamma_dist(rng_);
+    return std::gamma_distribution<>(k)(rng_) * theta;
   }
 
-  /// RNG from Beta distribution.
+  /// RNG from a Beta distribution.
   ///
   /// @param[in] alpha  Alpha shape parameter of Beta distribution.
   /// @param[in] beta  Beta shape parameter of Beta distribution.
@@ -195,14 +189,10 @@ class Random {
   static double BetaGenerator(double alpha, double beta) noexcept {
     assert(alpha > 0);
     assert(beta > 0);
-    std::gamma_distribution<double> gamma_dist_x(alpha);
-    std::gamma_distribution<double> gamma_dist_y(beta);
-    double x = gamma_dist_x(rng_);
-    double y = gamma_dist_y(rng_);
-    return x / (x + y);
+    return boost::random::beta_distribution<>(alpha, beta)(rng_);
   }
 
-  /// RNG from Weibull distribution.
+  /// RNG from a Weibull distribution.
   ///
   /// @param[in] k  Shape parameter of Weibull distribution.
   /// @param[in] lambda  Scale parameter of Weibull distribution.
@@ -211,43 +201,40 @@ class Random {
   static double WeibullGenerator(double k, double lambda) noexcept {
     assert(k > 0);
     assert(lambda > 0);
-    std::weibull_distribution<double> dist(k, lambda);
-    return dist(rng_);
+    return std::weibull_distribution<>(k, lambda)(rng_);
   }
 
-  /// RNG from Exponential distribution.
+  /// RNG from an Exponential distribution.
   ///
   /// @param[in] lambda  Rate parameter of Exponential distribution.
   ///
   /// @returns A sampled value.
   static double ExponentialGenerator(double lambda) noexcept {
     assert(lambda > 0);
-    std::exponential_distribution<double> dist(lambda);
-    return dist(rng_);
+    return std::exponential_distribution<>(lambda)(rng_);
   }
 
-  /// RNG from Poisson distribution.
+  /// RNG from a Poisson distribution.
   ///
   /// @param[in] mean  The mean value for Poisson distribution.
   ///
   /// @returns A sampled value.
   static int PoissonGenerator(int mean) noexcept {
     assert(mean > 0);
-    std::poisson_distribution<int> dist(mean);
-    return dist(rng_);
+    return std::poisson_distribution<>(mean)(rng_);
   }
 
-  /// RNG from log-uniform distribution.
+  /// RNG from a log-uniform distribution.
   ///
-  /// @param[in] min  Lower bound.
-  /// @param[in] max  Upper bound.
+  /// @param[in] lower  Lower bound.
+  /// @param[in] upper  Upper bound.
   ///
   /// @returns A sampled value.
-  static double LogUniformGenerator(double min, double max) noexcept {
-    return std::exp(UniformRealGenerator(min, max));
+  static double LogUniformGenerator(double lower, double upper) noexcept {
+    return std::exp(UniformRealGenerator(lower, upper));
   }
 
-  /// RNG from log-triangular distribution.
+  /// RNG from a log-triangular distribution.
   ///
   /// @param[in] lower  Lower bound.
   /// @param[in] mode  The peak of the distribution.
@@ -260,17 +247,6 @@ class Random {
   }
 
  private:
-  /// RNG from a discrete distribution.
-  ///
-  /// @param[in] weights  Weights for the range [0, n),
-  ///                     where n is the size of the vector.
-  ///
-  /// @returns Integer in the range [0, n).
-  static int DiscreteGenerator(const std::vector<double>& weights) noexcept {
-    std::discrete_distribution<int> dist(weights.begin(), weights.end());
-    return dist(rng_);
-  }
-
   static std::mt19937 rng_;  ///< The random number generator.
 };
 
diff --git a/src/reporter.cc b/src/reporter.cc
index 68be8ea..d8e7906 100644
--- a/src/reporter.cc
+++ b/src/reporter.cc
@@ -20,13 +20,16 @@
 
 #include "reporter.h"
 
+#include <fstream>
+#include <ostream>
 #include <vector>
 
 #include <boost/date_time.hpp>
 
 #include "ccf_group.h"
-#include "expression.h"
+#include "error.h"
 #include "logger.h"
+#include "parameter.h"
 #include "version.h"
 
 namespace scram {
@@ -58,6 +61,15 @@ void Reporter::Report(const core::RiskAnalysis& risk_an, std::ostream& out) {
   LOG(DEBUG1) << "Finished reporting in " << DUR(report_time);
 }
 
+void Reporter::Report(const core::RiskAnalysis& risk_an,
+                      const std::string& file) {
+  std::ofstream of(file.c_str());
+  if (!of.good())
+    throw IOError(file + " : Cannot write the output file.");
+
+  Report(risk_an, of);
+}
+
 /// Describes the fault tree analysis and techniques.
 template <>
 void Reporter::ReportCalculatedQuantity<core::FaultTreeAnalysis>(
diff --git a/src/reporter.h b/src/reporter.h
index 25e21fc..4f21c8a 100644
--- a/src/reporter.h
+++ b/src/reporter.h
@@ -21,7 +21,7 @@
 #ifndef SCRAM_SRC_REPORTER_H_
 #define SCRAM_SRC_REPORTER_H_
 
-#include <ostream>
+#include <iosfwd>
 #include <string>
 
 #include "event.h"
@@ -36,7 +36,7 @@
 
 namespace scram {
 
-/// This class reports the results of the analyses.
+/// Facilities to report analysis results.
 class Reporter {
  public:
   /// Reports the results of risk analysis on a model.
@@ -49,6 +49,15 @@ class Reporter {
   ///      There is going to be no appending to the stream after the report.
   void Report(const core::RiskAnalysis& risk_an, std::ostream& out);
 
+  /// A convenience function to generate the report into a file.
+  /// This function overwrites the file.
+  ///
+  /// @param[in] risk_an  Risk analysis with results.
+  /// @param[out] file  The output destination.
+  ///
+  /// @throws IOError  The output file is not accessible.
+  void Report(const core::RiskAnalysis& risk_an, const std::string& file);
+
  private:
   /// This function populates information
   /// about the software, settings, time, methods, model, etc.
diff --git a/src/risk_analysis.cc b/src/risk_analysis.cc
index 78241e1..52c087f 100644
--- a/src/risk_analysis.cc
+++ b/src/risk_analysis.cc
@@ -20,19 +20,12 @@
 
 #include "risk_analysis.h"
 
-#include <fstream>
-#include <utility>
-#include <vector>
-
 #include "bdd.h"
-#include "error.h"
-#include "expression.h"
+#include "ext.h"
 #include "fault_tree.h"
 #include "logger.h"
 #include "mocus.h"
-#include "model.h"
 #include "random.h"
-#include "reporter.h"
 #include "zbdd.h"
 
 namespace scram {
@@ -48,6 +41,7 @@ void RiskAnalysis::Analyze() noexcept {
   // Otherwise it defaults to the implementation dependent value.
   if (Analysis::settings().seed() >= 0)
     Random::seed(Analysis::settings().seed());
+
   for (const mef::FaultTreePtr& ft : model_->fault_trees()) {
     for (const mef::Gate* target : ft->top_events()) {
       LOG(INFO) << "Running analysis: " << target->id();
@@ -85,7 +79,7 @@ void RiskAnalysis::RunAnalysis(const std::string& name,
       RunAnalysis<Algorithm, McubCalculator>(name, fta);
     }
   }
-  fault_tree_analyses_.emplace(name, FaultTreeAnalysisPtr(fta));
+  fault_tree_analyses_.emplace(name, ext::make_unique(fta));
 }
 
 template <class Algorithm, class Calculator>
@@ -96,27 +90,14 @@ void RiskAnalysis::RunAnalysis(const std::string& name,
   if (Analysis::settings().importance_analysis()) {
     auto* ia = new ImportanceAnalyzer<Calculator>(pa);
     ia->Analyze();
-    importance_analyses_.emplace(name, ImportanceAnalysisPtr(ia));
+    importance_analyses_.emplace(name, ext::make_unique(ia));
   }
   if (Analysis::settings().uncertainty_analysis()) {
     auto* ua = new UncertaintyAnalyzer<Calculator>(pa);
     ua->Analyze();
-    uncertainty_analyses_.emplace(name, UncertaintyAnalysisPtr(ua));
-  }
-  probability_analyses_.emplace(name, ProbabilityAnalysisPtr(pa));
-}
-
-void RiskAnalysis::Report(std::ostream& out) {
-  Reporter rp = Reporter();
-  rp.Report(*this, out);
-}
-
-void RiskAnalysis::Report(std::string output) {
-  std::ofstream of(output.c_str());
-  if (!of.good()) {
-    throw IOError(output +  " : Cannot write the output file.");
+    uncertainty_analyses_.emplace(name, ext::make_unique(ua));
   }
-  Report(of);
+  probability_analyses_.emplace(name, ext::make_unique(pa));
 }
 
 }  // namespace core
diff --git a/src/risk_analysis.h b/src/risk_analysis.h
index ac15890..625a2ce 100644
--- a/src/risk_analysis.h
+++ b/src/risk_analysis.h
@@ -21,7 +21,6 @@
 #ifndef SCRAM_SRC_RISK_ANALYSIS_H_
 #define SCRAM_SRC_RISK_ANALYSIS_H_
 
-#include <iostream>
 #include <map>
 #include <memory>
 #include <string>
@@ -41,16 +40,11 @@ namespace core {
 /// Main system that performs analyses.
 class RiskAnalysis : public Analysis {
  public:
-  /// Pointer aliases for convenience.
-  /// @{
-  using FaultTreeAnalysisPtr = std::unique_ptr<FaultTreeAnalysis>;
-  using ProbabilityAnalysisPtr = std::unique_ptr<ProbabilityAnalysis>;
-  using ImportanceAnalysisPtr = std::unique_ptr<ImportanceAnalysis>;
-  using UncertaintyAnalysisPtr = std::unique_ptr<UncertaintyAnalysis>;
-  /// @}
+  /// A storage container type for analysis kinds
+  /// with their ids as keys.
+  template <class T>
+  using AnalysisTable = std::map<std::string, std::unique_ptr<T>>;
 
-  /// Constructs RiskAnalysis with a valid model and analysis settings.
-  ///
   /// @param[in] model  An analysis model with fault trees, events, etc.
   /// @param[in] settings  Analysis settings for the given model.
   RiskAnalysis(std::shared_ptr<const mef::Model> model,
@@ -59,64 +53,30 @@ class RiskAnalysis : public Analysis {
   /// @returns The model under analysis.
   const mef::Model& model() const { return *model_; }
 
-  /// Performs the main analysis operations.
-  /// Analyzes the fault tree and performs computations.
+  /// Analyzes the model
+  /// and performs computations specified in the settings.
   ///
   /// @note This function must be called
-  ///       only after initializing the model
+  ///       only after full initialization of the model
   ///       with or without its probabilities.
   void Analyze() noexcept;
 
-  /// Reports all results generated by all analyses
-  /// into XML formatted stream.
-  /// The report is appended to the stream.
-  ///
-  /// @param[out] out  The output stream.
-  ///
-  /// @note This function must be called only after Analyze() function.
-  void Report(std::ostream& out);
-
-  /// Reports the results of analyses
-  /// to a specified output destination.
-  /// This function overwrites the file.
-  ///
-  /// @param[out] output  The output destination.
-  ///
-  /// @throws IOError  The output file is not accessible.
-  ///
-  /// @note This function must be called only after Analyze() function.
-  void Report(std::string output);
-
-  /// @returns Fault tree analyses performed on one-top-event fault trees.
-  ///          The top gate identifier is used as the analysis identifier.
-  const std::map<std::string, FaultTreeAnalysisPtr>&
-  fault_tree_analyses() const {
+  /// @returns Containers of performed analyses
+  ///          identified by the top gate identifiers.
+  /// @{
+  const AnalysisTable<FaultTreeAnalysis>& fault_tree_analyses() const {
     return fault_tree_analyses_;
   }
-
-  /// @returns Probability analysis performed on
-  ///          Boolean products generated by
-  ///          fault tree analyses.
-  const std::map<std::string, ProbabilityAnalysisPtr>&
-  probability_analyses() const {
+  const AnalysisTable<ProbabilityAnalysis>& probability_analyses() const {
     return probability_analyses_;
   }
-
-  /// @returns Importance analysis performed on
-  ///          Boolean products generated by
-  ///          fault tree analyses.
-  const std::map<std::string, ImportanceAnalysisPtr>&
-  importance_analyses() const {
+  const AnalysisTable<ImportanceAnalysis>& importance_analyses() const {
     return importance_analyses_;
   }
-
-  /// @returns Uncertainty analyses performed on
-  ///          Boolean products generated by
-  ///          fault tree analyses.
-  const std::map<std::string, UncertaintyAnalysisPtr>&
-  uncertainty_analyses() const {
+  const AnalysisTable<UncertaintyAnalysis>& uncertainty_analyses() const {
     return uncertainty_analyses_;
   }
+  /// @}
 
  private:
   /// Runs all possible analysis on a given target.
@@ -150,15 +110,15 @@ class RiskAnalysis : public Analysis {
   void RunAnalysis(const std::string& name,
                    FaultTreeAnalyzer<Algorithm>* fta) noexcept;
 
-  /// Analysis model with constructs.
+  /// The analysis model with constructs.
   std::shared_ptr<const mef::Model> model_;
 
   /// Analyses performed by this risk analysis run.
   /// @{
-  std::map<std::string, FaultTreeAnalysisPtr> fault_tree_analyses_;
-  std::map<std::string, ProbabilityAnalysisPtr> probability_analyses_;
-  std::map<std::string, ImportanceAnalysisPtr> importance_analyses_;
-  std::map<std::string, UncertaintyAnalysisPtr> uncertainty_analyses_;
+  AnalysisTable<FaultTreeAnalysis> fault_tree_analyses_;
+  AnalysisTable<ProbabilityAnalysis> probability_analyses_;
+  AnalysisTable<ImportanceAnalysis> importance_analyses_;
+  AnalysisTable<UncertaintyAnalysis> uncertainty_analyses_;
   /// @}
 };
 
diff --git a/src/scram.cc b/src/scram.cc
index 6d307fa..ed2dde6 100644
--- a/src/scram.cc
+++ b/src/scram.cc
@@ -30,6 +30,7 @@
 #include "error.h"
 #include "initializer.h"
 #include "logger.h"
+#include "reporter.h"
 #include "risk_analysis.h"
 #include "settings.h"
 #include "version.h"
@@ -240,10 +241,11 @@ void RunScram(const po::variables_map& vm) {
   if (vm.count("no-report") || vm.count("preprocessor") || vm.count("print"))
     return;
 #endif
+  scram::Reporter reporter;
   if (output_path.empty()) {
-    analysis->Report(std::cout);
+    reporter.Report(*analysis, std::cout);
   } else {
-    analysis->Report(output_path);
+    reporter.Report(*analysis, output_path);
   }
 }
 
@@ -252,10 +254,10 @@ void RunScram(const po::variables_map& vm) {
 /// Catches an exception,
 /// prints its message to the standard error,
 /// and returns error code of 1 to exit from the main function.
-#define CATCH(exception_type, header)                        \
-  catch (const exception_type& err) {                        \
-    std::cerr << header << ":\n" << err.what() << std::endl; \
-    return 1;                                                \
+#define CATCH(exception_type)                                         \
+  catch (const exception_type& err) {                                 \
+    std::cerr << #exception_type << ":\n" << err.what() << std::endl; \
+    return 1;                                                         \
   }
 
 /// Command-line SCRAM entrance.
@@ -280,19 +282,19 @@ int main(int argc, char* argv[]) {
 
 #ifdef NDEBUG
   }
-  CATCH(scram::IOError, "SCRAM I/O Error")
-  CATCH(scram::ValidationError, "SCRAM Validation Error")
-  CATCH(scram::ValueError, "SCRAM Value Error")
-  CATCH(scram::LogicError, "SCRAM Logic Error")
-  CATCH(scram::IllegalOperation, "SCRAM Illegal Operation")
-  CATCH(scram::InvalidArgument, "SCRAM Invalid Argument Error")
-  CATCH(scram::Error, "SCRAM Error")
+  CATCH(scram::IOError)
+  CATCH(scram::ValidationError)
+  CATCH(scram::ValueError)
+  CATCH(scram::LogicError)
+  CATCH(scram::IllegalOperation)
+  CATCH(scram::InvalidArgument)
+  CATCH(scram::Error)
   catch (boost::exception& boost_err) {
     std::cerr << "Boost Exception:\n"
               << boost::diagnostic_information(boost_err) << std::endl;
     return 1;
   }
-  CATCH(std::exception, "Standard Exception")
+  CATCH(std::exception)
 #endif
 }  // End of main.
 #undef CATCH
diff --git a/src/settings.h b/src/settings.h
index 101a3f8..d8d9dfe 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -167,6 +167,8 @@ class Settings {
   /// @param[in] time  A positive number in hours by default.
   ///
   /// @returns Reference to this object.
+  ///
+  /// @throws InvalidArgument  The time value is negative.
   Settings& mission_time(double time);
 
   /// @returns true if probability analysis is requested.
diff --git a/src/uncertainty_analysis.cc b/src/uncertainty_analysis.cc
index 7d75d12..92a808d 100644
--- a/src/uncertainty_analysis.cc
+++ b/src/uncertainty_analysis.cc
@@ -29,6 +29,7 @@
 #include <boost/accumulators/statistics/stats.hpp>
 #include <boost/accumulators/statistics/variance.hpp>
 
+#include "event.h"
 #include "logger.h"
 
 namespace scram {
@@ -70,6 +71,20 @@ UncertaintyAnalysis::FilterUncertainEvents(const BooleanGraph* graph) noexcept {
   return uncertain_events;
 }
 
+void UncertaintyAnalysis::SampleEventProbabilities(
+    const std::vector<std::pair<int, mef::BasicEvent*>>& uncertain_events,
+    std::vector<double>* p_vars) noexcept {
+  // Reset distributions.
+  for (const auto& event : uncertain_events)
+    event.second->Reset();
+
+  // Sample all basic events with distributions.
+  for (const auto& event : uncertain_events) {
+    double prob = event.second->SampleProbability();
+    (*p_vars)[event.first] = prob > 1 ? 1 : prob < 0 ? 0 : prob;
+  }
+}
+
 void UncertaintyAnalysis::CalculateStatistics(
     const std::vector<double>& samples) noexcept {
   using namespace boost;  // NOLINT
diff --git a/src/uncertainty_analysis.h b/src/uncertainty_analysis.h
index 082799c..5db5f86 100644
--- a/src/uncertainty_analysis.h
+++ b/src/uncertainty_analysis.h
@@ -26,11 +26,15 @@
 #include <vector>
 
 #include "analysis.h"
-#include "event.h"
 #include "probability_analysis.h"
 #include "settings.h"
 
 namespace scram {
+
+namespace mef {  // Decouple from the implementation dependence.
+class BasicEvent;
+}  // namespace mef
+
 namespace core {
 
 /// Uncertainty analysis and statistics
@@ -83,6 +87,18 @@ class UncertaintyAnalysis : public Analysis {
   std::vector<std::pair<int, mef::BasicEvent*>> FilterUncertainEvents(
       const BooleanGraph* graph) noexcept;
 
+  /// Samples each uncertain event probability.
+  ///
+  /// @param[in] uncertain_events  A collection of uncertain events.
+  /// @param[in,out] p_vars  A container for sampled event probabilities.
+  ///
+  /// @pre The container for probabilities is large enough
+  ///      to have the resultant probabilities get mapped by indices.
+  ///      That is, container[event.index()] never fails for any given event.
+  void SampleEventProbabilities(
+      const std::vector<std::pair<int, mef::BasicEvent*>>& uncertain_events,
+      std::vector<double>* p_vars) noexcept;
+
  private:
   /// Performs Monte Carlo Simulation
   /// by sampling the probability distributions
@@ -118,11 +134,6 @@ class UncertaintyAnalyzer : public UncertaintyAnalysis {
   /// to calculate the total probability for sampling.
   ///
   /// @param[in] prob_analyzer  Instantiated probability analyzer.
-  ///
-  /// @pre Probability analyzer can work with modified probability values.
-  ///
-  /// @post Probability analyzer's probability values are
-  ///       reset to the original values (event probabilities).
   explicit UncertaintyAnalyzer(ProbabilityAnalyzer<Calculator>* prob_analyzer)
       : UncertaintyAnalysis(prob_analyzer),
         prob_analyzer_(prob_analyzer) {}
@@ -139,33 +150,16 @@ template <class Calculator>
 std::vector<double> UncertaintyAnalyzer<Calculator>::Sample() noexcept {
   std::vector<std::pair<int, mef::BasicEvent*>> uncertain_events =
       UncertaintyAnalysis::FilterUncertainEvents(prob_analyzer_->graph());
-  std::vector<double>& p_vars = prob_analyzer_->p_vars();
+  std::vector<double> p_vars = prob_analyzer_->p_vars();  // Private copy!
   std::vector<double> samples;
   samples.reserve(Analysis::settings().num_trials());
+
   for (int i = 0; i < Analysis::settings().num_trials(); ++i) {
-    // Reset distributions.
-    for (const auto& event : uncertain_events)
-      event.second->Reset();
-
-    // Sample all basic events with distributions.
-    for (const auto& event : uncertain_events) {
-      double prob = event.second->SampleProbability();
-      if (prob < 0) {  // Adjust if out of range.
-        prob = 0;
-      } else if (prob > 1) {
-        prob = 1;
-      }
-      p_vars[event.first] = prob;
-    }
-    double result = prob_analyzer_->CalculateTotalProbability();
-    assert(result >= 0);
-    if (result > 1)
-      result = 1;
+    UncertaintyAnalysis::SampleEventProbabilities(uncertain_events, &p_vars);
+    double result = prob_analyzer_->CalculateTotalProbability(p_vars);
+    assert(result >= 0 && result <= 1);
     samples.push_back(result);
   }
-  // Reset probabilities.
-  for (const auto& event : uncertain_events)
-    p_vars[event.first] = event.second->p();
 
   return samples;
 }
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f76f5c4..a8c76c1 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -6,7 +6,7 @@ set(CMAKE_CXX_FLAGS_DEBUG "-g")
 
 set(GTEST_DIR  "${CMAKE_CURRENT_SOURCE_DIR}/googletest/googletest")
 
-add_subdirectory("${GTEST_DIR}")
+add_subdirectory("${GTEST_DIR}" EXCLUDE_FROM_ALL)
 
 set(CMAKE_CXX_FLAGS_DEBUG "${CURRENT_DEBUG_FLAGS}")  # Restore the original flags.
 
diff --git a/tests/bench_bscu_tests.cc b/tests/bench_bscu_tests.cc
index ae76a8f..1476910 100644
--- a/tests/bench_bscu_tests.cc
+++ b/tests/bench_bscu_tests.cc
@@ -48,12 +48,12 @@ TEST_P(RiskAnalysisTest, BSCU) {
 
   if (settings.approximation() == "rare-event") {
     EXPECT_NEAR(0.135372, p_total(), 1e-4);
-    EXPECT_NEAR(0.1448961, mean(), 5e-3);
-    EXPECT_NEAR(0.203192, sigma(), 5e-3);
+    EXPECT_NEAR(0.137, mean(), 5e-3);
+    EXPECT_NEAR(0.217, sigma(), 5e-3);
   } else {
     EXPECT_NEAR(0.1124087, p_total(), 1e-4);
-    EXPECT_NEAR(0.1212541, mean(), 5e-3);
-    EXPECT_NEAR(0.1646726, sigma(), 5e-3);
+    EXPECT_NEAR(0.117, mean(), 5e-3);
+    EXPECT_NEAR(0.183, sigma(), 5e-3);
   }
 }
 
diff --git a/tests/bench_core_tests.cc b/tests/bench_core_tests.cc
index 717afd6..456494a 100644
--- a/tests/bench_core_tests.cc
+++ b/tests/bench_core_tests.cc
@@ -455,9 +455,9 @@ TEST_P(RiskAnalysisTest, AlphaFactorCCF) {
   ASSERT_NO_THROW(ProcessInputFile(tree_input));
   ASSERT_NO_THROW(analysis->Analyze());
   if (settings.approximation() == "rare-event") {
-    EXPECT_NEAR(0.03234, p_total(), 1e-5);
+    EXPECT_NEAR(0.05488, p_total(), 1e-5);
   } else {
-    EXPECT_NEAR(0.03092, p_total(), 1e-5);
+    EXPECT_NEAR(0.05298, p_total(), 1e-5);
   }
   EXPECT_EQ(34, products().size());
   std::vector<int> distr = {2, 24, 8};
diff --git a/tests/bench_small_tree_tests.cc b/tests/bench_small_tree_tests.cc
index 5c51082..6eb38d9 100644
--- a/tests/bench_small_tree_tests.cc
+++ b/tests/bench_small_tree_tests.cc
@@ -34,8 +34,15 @@ TEST_P(RiskAnalysisTest, SmallTree) {
   std::set<std::set<std::string>> mcs = {{"e1", "e2"}, {"e3", "e4"}};
   EXPECT_EQ(2, products().size());
   EXPECT_EQ(mcs, products());
-  EXPECT_NEAR(0.02569, mean(), 1e-3);
-  EXPECT_NEAR(0.018065, sigma(), 2e-3);
+  if (settings.approximation() == "rare-event") {
+    EXPECT_NEAR(0.02696, p_total(), 1e-5);
+    EXPECT_NEAR(0.0255, mean(), 1e-3);
+    EXPECT_NEAR(0.0225, sigma(), 2e-3);
+  } else {
+    EXPECT_NEAR(0.02678, p_total(), 1e-5);
+    EXPECT_NEAR(0.0253, mean(), 1e-3);
+    EXPECT_NEAR(0.022, sigma(), 2e-3);
+  }
 }
 
 }  // namespace test
diff --git a/tests/ccf_group_tests.cc b/tests/ccf_group_tests.cc
index ae9b549..f6d1570 100644
--- a/tests/ccf_group_tests.cc
+++ b/tests/ccf_group_tests.cc
@@ -20,6 +20,7 @@
 #include <gtest/gtest.h>
 
 #include "error.h"
+#include "expression/constant.h"
 
 namespace scram {
 namespace mef {
diff --git a/tests/expression_tests.cc b/tests/expression_tests.cc
index 7af0f96..67b5fd4 100644
--- a/tests/expression_tests.cc
+++ b/tests/expression_tests.cc
@@ -16,6 +16,10 @@
  */
 
 #include "expression.h"
+#include "expression/arithmetic.h"
+#include "expression/exponential.h"
+#include "expression/random_deviate.h"
+#include "parameter.h"
 
 #include <gtest/gtest.h>
 
diff --git a/tests/input/empty_attribute.xml b/tests/input/empty_attribute.xml
index bfeff69..854abbe 100644
--- a/tests/input/empty_attribute.xml
+++ b/tests/input/empty_attribute.xml
@@ -3,7 +3,7 @@
   <define-fault-tree name="Ex">
     <define-basic-event name="A">
       <attributes>
-        <attribute value=""/>
+        <attribute name="attribute" value=""/>
       </attributes>
       <float value="0.1"/>
     </define-basic-event>
diff --git a/tests/input/fta/doubly_defined_parameter.xml b/tests/input/fta/doubly_defined_parameter.xml
index 5005073..244cc77 100644
--- a/tests/input/fta/doubly_defined_parameter.xml
+++ b/tests/input/fta/doubly_defined_parameter.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 This input contains a paremeter that is doubly defined.
-This input may be valid OpenPSA MEF with optional warnings.
+This input may be valid Open-PSA MEF with optional warnings.
 -->
 <opsa-mef>
   <define-fault-tree name="TwoTrains">
diff --git a/tests/input/fta/run_inputs.py b/tests/input/fta/run_inputs.py
index 4b217b5..838c4ac 100755
--- a/tests/input/fta/run_inputs.py
+++ b/tests/input/fta/run_inputs.py
@@ -20,7 +20,6 @@
 from __future__ import print_function
 
 import subprocess
-import sys
 
 
 # Input that must be analyzed with the results printed.
@@ -123,81 +122,42 @@ BLOCK_DELIM = "=" * 80
 FILE_DELIM = "-" * 80
 
 
-def main():
-    """Runs SCRAM with all registered inputs."""
-    # Run correct inputs
-    print("\nRUNNING CORRECT INPUTS WITH OUTPUT")
-    print(BLOCK_DELIM)
-    for i in PRINT_INPUTS:
-        print("\nRUNNING : " + i)
-        print(FILE_DELIM)
-        args = ["scram", i]
-        subprocess.call(args)
-        print(FILE_DELIM)
-    print(BLOCK_DELIM)
+def run_inputs(title, inputs, flags):
+    """Runs each input with scram.
 
-    # Run correct inputs
-    print("\nVALIDATING CORRECT INPUTS WITHOUT PROBABILITY CALCULATION")
+    Args:
+        title: The group title for the inputs and the run.
+        inputs: The input files.
+        flags: A list of flags to be prepended before the argument file.
+    """
+    print("\n%s" % title.upper())
     print(BLOCK_DELIM)
-    for i in PASS_INPUTS:
-        print("\nVALIDATING : " + i)
+    for i in inputs:
+        print("\n%s : " % title.split()[0].upper() + i)
         print(FILE_DELIM)
-        args = ["scram", i, "--validate"]
-        subprocess.call(args)
+        subprocess.call(["scram"] + flags + [i])
         print(FILE_DELIM)
     print(BLOCK_DELIM)
 
-    # Run incorrect inputs
-    print("\nVALIDATING INCORRECT INPUTS WITHOUT PROBABILITY CALCULATION")
-    print(BLOCK_DELIM)
-    for i in BAD_INPUTS:
-        print("\nVALIDATING : " + i)
-        print(FILE_DELIM)
-        args = ["scram", i, "--validate"]
-        try:
-            subprocess.check_call(args)
-        except subprocess.CalledProcessError:
-            print(sys.exc_info()[0])
-        print(FILE_DELIM)
-    print(BLOCK_DELIM)
-
-    # Run correct inputs with probabilities
-    print("\nVALIDATING CORRECT PROBABILITY INPUTS")
-    print(BLOCK_DELIM)
-    for i in PASS_PROBS:
-        print("\nVALIDATING : " + i)
-        print(FILE_DELIM)
-        args = ["scram", i, "--probability", "1", "--validate"]
-        subprocess.call(args)
-        print(FILE_DELIM)
-    print(BLOCK_DELIM)
 
-    # Run incorrect inputs with probability calculations
-    print("\nVALIDATING INCORRECT PROBABILITY INPUTS")
-    print(BLOCK_DELIM)
-    for i in BAD_PROBS:
-        print("\nVALIDATING : " + i)
-        print(FILE_DELIM)
-        args = ["scram", i, "--probability", "1", "--validate"]
-        try:
-            subprocess.check_call(args)
-        except subprocess.CalledProcessError:
-            print(sys.exc_info()[0])
-        print(FILE_DELIM)
-    print(BLOCK_DELIM)
+def main():
+    """Runs SCRAM with all registered inputs."""
+    # Run correct inputs
+    run_inputs("running correct inputs with output", PRINT_INPUTS, [])
+    run_inputs("validating correct inputs w/o probability calculation",
+               PASS_INPUTS, ["--validate"])
+    run_inputs("validating correct probability inputs", PASS_PROBS,
+               ["--probability", "1", "--validate"])
 
-    print("\nVALIDATING INCORRECT CONFIGURATION FILES")
-    print(BLOCK_DELIM)
-    for i in BAD_CONFIG:
-        print("\nVALIDATING : " + i)
-        print(FILE_DELIM)
-        args = ["scram", "--config-file", i, "--validate"]
-        try:
-            subprocess.check_call(args)
-        except subprocess.CalledProcessError:
-            print(sys.exc_info()[0])
-        print(FILE_DELIM)
-    print(BLOCK_DELIM)
+    # Run incorrect inputs
+    run_inputs("validating incorrect inputs w/o probability calculation",
+               BAD_INPUTS, ["--validate"])
+    run_inputs("validating incorrect probability inputs", BAD_PROBS,
+               ["--probability", "1", "--validate"])
+
+    # Incorrect configurations
+    run_inputs("validating incorrect configuration files", BAD_CONFIG,
+               ["--validate", "--config-file"])
 
 if __name__ == "__main__":
     main()
diff --git a/tests/input/unsupported_feature.xml b/tests/input/unsupported_feature.xml
index ac9f469..6e0ac23 100644
--- a/tests/input/unsupported_feature.xml
+++ b/tests/input/unsupported_feature.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 This input contains unsupported feature by SCRAM.
-However, this feature is valid in OpenPSA MEF.
+However, this feature is valid in the Open-PSA MEF.
 -->
 <opsa-mef>
   <define-substitution name="Backup">
diff --git a/tests/performance_tests.cc b/tests/performance_tests.cc
index f872abe..be36bb5 100644
--- a/tests/performance_tests.cc
+++ b/tests/performance_tests.cc
@@ -29,7 +29,7 @@
 //
 //   Proc         Core i7-2820QM
 //   Ubuntu       16.04 64bit
-//   GCC          5.3.1
+//   GCC          5.4.0
 //   Boost        1.58
 //   TCMalloc     2.4
 //
@@ -56,7 +56,6 @@ namespace test {
 TEST(RegressionTest, ObjectSize) {
   // x86-64 platform.
   // 64-bit platform with alignment at 8-byte boundaries.
-  EXPECT_EQ(16, sizeof(ControlBlock));
   EXPECT_EQ(8, sizeof(WeakIntrusivePtr<Vertex<Ite>>));
   EXPECT_EQ(8, sizeof(IntrusivePtr<Vertex<Ite>>));
   EXPECT_EQ(16, sizeof(Vertex<Ite>));
diff --git a/tests/risk_analysis_tests.cc b/tests/risk_analysis_tests.cc
index e88606a..db1862f 100644
--- a/tests/risk_analysis_tests.cc
+++ b/tests/risk_analysis_tests.cc
@@ -17,9 +17,15 @@
 
 #include "risk_analysis_tests.h"
 
+#include <sstream>
 #include <utility>
 
+#include <libxml++/libxml++.h>
+
+#include "env.h"
 #include "error.h"
+#include "initializer.h"
+#include "reporter.h"
 
 namespace scram {
 namespace core {
@@ -28,6 +34,97 @@ namespace test {
 const std::set<std::set<std::string>> RiskAnalysisTest::kUnity = {
     std::set<std::string>{}};
 
+void RiskAnalysisTest::SetUp() {
+  if (HasParam()) {
+    std::string param = GetParam();
+    if (param == "pi") {
+      settings.algorithm("bdd");
+      settings.prime_implicants(true);
+    } else {
+      settings.algorithm(GetParam());
+    }
+  }
+}
+
+void RiskAnalysisTest::ProcessInputFiles(
+    const std::vector<std::string>& input_files) {
+  mef::Initializer init(input_files, settings);
+  model = init.model();
+  analysis = std::make_unique<RiskAnalysis>(model, settings);
+  result_ = Result();
+}
+
+void RiskAnalysisTest::CheckReport(const std::string& tree_input) {
+  static xmlpp::RelaxNGValidator validator(Env::report_schema());
+
+  ASSERT_NO_THROW(ProcessInputFile(tree_input));
+  ASSERT_NO_THROW(analysis->Analyze());
+  std::stringstream output;
+  ASSERT_NO_THROW(Reporter().Report(*analysis, output));
+
+  xmlpp::DomParser parser;
+  ASSERT_NO_THROW(parser.parse_stream(output));
+  ASSERT_NO_THROW(validator.validate(parser.get_document()));
+}
+
+const std::set<std::set<std::string>>& RiskAnalysisTest::products() {
+  assert(!analysis->fault_tree_analyses().empty());
+  assert(analysis->fault_tree_analyses().size() == 1);
+  if (result_.products.empty()) {
+    const FaultTreeAnalysis* fta =
+        analysis->fault_tree_analyses().begin()->second.get();
+    for (const Product& product : fta->products()) {
+      result_.products.emplace(Convert(product));
+    }
+  }
+  return result_.products;
+}
+
+std::vector<int> RiskAnalysisTest::ProductDistribution() {
+  assert(!analysis->fault_tree_analyses().empty());
+  assert(analysis->fault_tree_analyses().size() == 1);
+  std::vector<int> distr(settings.limit_order(), 0);
+  const FaultTreeAnalysis* fta =
+      analysis->fault_tree_analyses().begin()->second.get();
+  for (const Product& product : fta->products()) {
+    distr[GetOrder(product) - 1]++;
+  }
+  while (!distr.empty() && !distr.back())
+    distr.pop_back();
+  return distr;
+}
+
+void RiskAnalysisTest::PrintProducts() {
+  assert(!analysis->fault_tree_analyses().empty());
+  assert(analysis->fault_tree_analyses().size() == 1);
+  const FaultTreeAnalysis* fta =
+      analysis->fault_tree_analyses().begin()->second.get();
+  Print(fta->products());
+}
+
+const std::map<std::set<std::string>, double>&
+RiskAnalysisTest::product_probability() {
+  assert(!analysis->fault_tree_analyses().empty());
+  assert(analysis->fault_tree_analyses().size() == 1);
+  if (result_.product_probability.empty()) {
+    const FaultTreeAnalysis* fta =
+        analysis->fault_tree_analyses().begin()->second.get();
+    for (const Product& product : fta->products()) {
+      result_.product_probability.emplace(Convert(product),
+                                          CalculateProbability(product));
+    }
+  }
+  return result_.product_probability;
+}
+
+std::set<std::string> RiskAnalysisTest::Convert(const Product& product) {
+  std::set<std::string> string_set;
+  for (const Literal& literal : product) {
+    string_set.insert((literal.complement ? "not " : "") + literal.event.id());
+  }
+  return string_set;
+}
+
 TEST_F(RiskAnalysisTest, ProcessInput) {
   std::string tree_input = "./share/scram/input/fta/correct_tree_input.xml";
   ASSERT_NO_THROW(ProcessInputFile(tree_input));
@@ -281,7 +378,7 @@ TEST_F(RiskAnalysisTest, ReportIOError) {
   std::string output = "abracadabra.cadabraabra/output.txt";
   ASSERT_NO_THROW(ProcessInputFile(tree_input));
   ASSERT_NO_THROW(analysis->Analyze());
-  EXPECT_THROW(analysis->Report(output), IOError);
+  EXPECT_THROW(Reporter().Report(*analysis, output), IOError);
 }
 
 // Reporting of the default analysis for MCS only without probabilities.
diff --git a/tests/risk_analysis_tests.h b/tests/risk_analysis_tests.h
index 7318498..c427b44 100644
--- a/tests/risk_analysis_tests.h
+++ b/tests/risk_analysis_tests.h
@@ -20,19 +20,11 @@
 
 #include "risk_analysis.h"
 
-#include <fstream>
-#include <map>
 #include <set>
-#include <sstream>
-#include <string>
 #include <vector>
 
 #include <gtest/gtest.h>
 
-#include "env.h"
-#include "initializer.h"
-#include "xml.h"
-
 namespace scram {
 namespace core {
 namespace test {
@@ -41,106 +33,44 @@ class RiskAnalysisTest : public ::testing::TestWithParam<const char*> {
  protected:
   static const std::set<std::set<std::string>> kUnity;  ///< Special unity set.
 
-  void SetUp() override {
-    if (HasParam()) {
-      std::string param = GetParam();
-      if (param == "pi") {
-        settings.algorithm("bdd");
-        settings.prime_implicants(true);
-      } else {
-        settings.algorithm(GetParam());
-      }
-    }
-  }
-
-  void TearDown() override {}
+  void SetUp() override;
 
   // Parsing multiple input files.
-  void ProcessInputFiles(const std::vector<std::string>& input_files) {
-    init = std::make_unique<mef::Initializer>(input_files, settings);
-    ResetRiskAnalysis();
-  }
-
-  // Resets the risk analysis with the initialized model and settings.
-  void ResetRiskAnalysis() {
-    assert(init && "Missing initializer");
-    analysis = std::make_unique<RiskAnalysis>(init->model(), settings);
-  }
+  void ProcessInputFiles(const std::vector<std::string>& input_files);
 
   // Parsing an input file to get the model.
   void ProcessInputFile(const std::string& input_file) {
-    std::vector<std::string> input_files;
-    input_files.push_back(input_file);
-    ProcessInputFiles(input_files);
+    ProcessInputFiles({input_file});
   }
 
   // Collection of assertions on the reporting after running analysis.
   // Note that the analysis is run by this function.
-  void CheckReport(const std::string& tree_input) {
-    static xmlpp::RelaxNGValidator validator(Env::report_schema());
-
-    ASSERT_NO_THROW(ProcessInputFile(tree_input));
-    ASSERT_NO_THROW(analysis->Analyze());
-    std::stringstream output;
-    ASSERT_NO_THROW(analysis->Report(output));
-
-    xmlpp::DomParser parser;
-    ASSERT_NO_THROW(parser.parse_stream(output));
-    ASSERT_NO_THROW(validator.validate(parser.get_document()));
-  }
+  void CheckReport(const std::string& tree_input);
 
   // Returns a single fault tree, assuming one fault tree with single top gate.
   const mef::FaultTreePtr& fault_tree() {
-    return *init->model()->fault_trees().begin();
+    return *model->fault_trees().begin();
   }
 
-  const mef::IdTable<mef::GatePtr>& gates() { return init->model()->gates(); }
+  const mef::IdTable<mef::GatePtr>& gates() { return model->gates(); }
 
   const mef::IdTable<mef::HouseEventPtr>& house_events() {
-    return init->model()->house_events();
+    return model->house_events();
   }
 
   const mef::IdTable<mef::BasicEventPtr>& basic_events() {
-    return init->model()->basic_events();
+    return model->basic_events();
   }
 
-  const std::set<std::set<std::string>>& products() {
-    assert(!analysis->fault_tree_analyses().empty());
-    assert(analysis->fault_tree_analyses().size() == 1);
-    if (products_.empty()) {
-      const FaultTreeAnalysis* fta =
-          analysis->fault_tree_analyses().begin()->second.get();
-      for (const Product& product : fta->products()) {
-        products_.emplace(Convert(product));
-      }
-    }
-    return products_;
-  }
+  /// @returns The resultant products of the fault tree analysis.
+  const std::set<std::set<std::string>>& products();
 
   // Provides the number of products per order of sets.
   // The order starts from 1.
-  std::vector<int> ProductDistribution() {
-    assert(!analysis->fault_tree_analyses().empty());
-    assert(analysis->fault_tree_analyses().size() == 1);
-    std::vector<int> distr(settings.limit_order(), 0);
-    const FaultTreeAnalysis* fta =
-        analysis->fault_tree_analyses().begin()->second.get();
-    for (const Product& product : fta->products()) {
-      distr[GetOrder(product) - 1]++;
-    }
-    while (!distr.empty() && !distr.back())
-      distr.pop_back();
-    return distr;
-  }
+  std::vector<int> ProductDistribution();
 
   /// Prints products to the standard error.
-  void PrintProducts() {
-    assert(!analysis->fault_tree_analyses().empty());
-    assert(analysis->fault_tree_analyses().size() == 1);
-    const FaultTreeAnalysis* fta =
-        analysis->fault_tree_analyses().begin()->second.get();
-    Print(fta->products());
-  }
+  void PrintProducts();
 
   double p_total() {
     assert(!analysis->probability_analyses().empty());
@@ -148,19 +78,8 @@ class RiskAnalysisTest : public ::testing::TestWithParam<const char*> {
     return analysis->probability_analyses().begin()->second->p_total();
   }
 
-  const std::map<std::set<std::string>, double>& product_probability() {
-    assert(!analysis->fault_tree_analyses().empty());
-    assert(analysis->fault_tree_analyses().size() == 1);
-    if (product_probability_.empty()) {
-      const FaultTreeAnalysis* fta =
-          analysis->fault_tree_analyses().begin()->second.get();
-      for (const Product& product : fta->products()) {
-        product_probability_.emplace(Convert(product),
-                                     CalculateProbability(product));
-      }
-    }
-    return product_probability_;
-  }
+  /// @returns Products and their probabilities.
+  const std::map<std::set<std::string>, double>& product_probability();
 
   const ImportanceFactors& importance(std::string id) {
     assert(!analysis->importance_analyses().empty());
@@ -181,26 +100,21 @@ class RiskAnalysisTest : public ::testing::TestWithParam<const char*> {
     return analysis->uncertainty_analyses().begin()->second->sigma();
   }
 
-  /// Converts a set of pointers to events with complement flags
-  /// into readable and testable strings.
-  /// Complements are communicated with "not" prefix.
-  std::set<std::string> Convert(const Product& product) {
-    std::set<std::string> string_set;
-    for (const Literal& literal : product) {
-      string_set.insert((literal.complement ? "not " : "") +
-                        literal.event.id());
-    }
-    return string_set;
-  }
-
   // Members
   std::unique_ptr<RiskAnalysis> analysis;
-  std::unique_ptr<mef::Initializer> init;
+  std::shared_ptr<mef::Model> model;
   Settings settings;
 
  private:
-  std::map<std::set<std::string>, double> product_probability_;
-  std::set<std::set<std::string>> products_;
+  /// Converts a set of pointers to events with complement flags
+  /// into readable and testable strings.
+  /// Complements are communicated with "not" prefix.
+  std::set<std::string> Convert(const Product& product);
+
+  struct Result {
+    std::map<std::set<std::string>, double> product_probability;
+    std::set<std::set<std::string>> products;
+  } result_;
 };
 
 }  // namespace test
diff --git a/tests/test_scram_call.py b/tests/test_scram_call.py
index a9dbf80..c8a04e8 100644
--- a/tests/test_scram_call.py
+++ b/tests/test_scram_call.py
@@ -18,7 +18,7 @@
 import os
 from subprocess import call
 
-from nose.tools import assert_true, assert_equal, assert_not_equal
+from nose.tools import assert_equal, assert_not_equal
 
 
 def test_empty_call():

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/scram.git



More information about the debian-science-commits mailing list