[med-svn] [libbpp-core] 03/05: New upstream version 2.3.0
Andreas Tille
tille at debian.org
Thu Jun 1 14:03:21 UTC 2017
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository libbpp-core.
commit d1b91414a2cbcb1a41c05bbe706d9fee5a74e82d
Author: Andreas Tille <tille at debian.org>
Date: Thu Jun 1 15:58:49 2017 +0200
New upstream version 2.3.0
---
.gitignore | 15 +
AUTHORS.txt | 3 +
CMakeLists.txt | 137 +-
CTestConfig.cmake | 13 +
ChangeLog | 8 +
Doxyfile | 420 +++---
INSTALL.txt | 19 +-
bpp-core.spec | 104 +-
cmake/doc-cmake-for-developpers.cmake | 240 ++++
cmake/project-template-for-users.cmake | 106 ++
debian/changelog | 46 -
debian/compat | 1 -
debian/control | 22 -
debian/copyright | 74 --
debian/docs | 0
debian/libbpp-core-dev.install | 3 -
debian/libbpp-core2.install | 1 -
debian/postinst | 57 -
debian/postrm | 59 -
debian/prerm | 41 -
debian/rules | 122 --
debian/source/format | 1 -
genIncludes.sh | 35 -
package.cmake.in | 25 +
src/Bpp/App/ApplicationTools.cpp | 39 -
src/Bpp/App/ApplicationTools.h | 41 +-
src/Bpp/App/NumCalcApplicationTools.cpp | 1 +
src/Bpp/BppBoolean.h | 7 +-
src/Bpp/BppString.h | 7 +-
src/Bpp/BppVector.h | 7 +-
src/Bpp/Clonable.h | 32 +-
src/Bpp/Exceptions.cpp | 6 -
src/Bpp/Exceptions.h | 7 +-
src/Bpp/Graph/AssociationDAGraphImplObserver.h | 406 ++++++
src/Bpp/Graph/AssociationDAGraphObserver.h | 256 ++++
src/Bpp/Graph/AssociationGraphImplObserver.h | 1332 ++++++++++++++++++++
src/Bpp/Graph/AssociationGraphObserver.h | 483 +++++++
src/Bpp/Graph/AssociationTreeGraphImplObserver.h | 397 ++++++
src/Bpp/Graph/AssociationTreeGraphObserver.h | 255 ++++
src/Bpp/Graph/BasicTNode.cpp | 208 ---
src/Bpp/Graph/BasicTNode.h | 160 ---
src/Bpp/Graph/DAGraph.h | 174 +++
src/Bpp/Graph/DAGraphImpl.h | 525 ++++++++
src/Bpp/Graph/GlobalGraph.cpp | 990 +++++++++++++++
src/Bpp/Graph/GlobalGraph.h | 956 ++++++++++++++
src/Bpp/Graph/Graph.h | 582 +++++++++
.../GraphObserver.h} | 97 +-
src/Bpp/Graph/ONode.h | 170 ---
src/Bpp/Graph/TNode.h | 129 --
src/Bpp/Graph/TreeGraph.h | 201 +++
src/Bpp/Graph/TreeGraphImpl.h | 593 +++++++++
src/Bpp/Graph/UNode.h | 123 --
src/Bpp/Graphics/Font/Font.h | 7 +-
src/Bpp/Graphics/Font/FontManager.h | 1 +
src/Bpp/Graphics/RgbColor.h | 7 +-
src/Bpp/Io/BppODiscreteDistributionFormat.cpp | 19 +-
src/Bpp/Io/OutputStream.h | 10 +-
src/Bpp/Numeric/AbstractParameterAliasable.cpp | 206 ++-
src/Bpp/Numeric/AbstractParameterAliasable.h | 443 +++----
src/Bpp/Numeric/AbstractParametrizable.h | 95 +-
src/Bpp/Numeric/AutoParameter.cpp | 134 +-
src/Bpp/Numeric/DataTable.h | 3 +-
src/Bpp/Numeric/DataTableExceptions.h | 175 ---
.../Numeric/Function/AbstractNumericalDerivative.h | 51 +-
src/Bpp/Numeric/Function/BrentOneDimension.cpp | 2 +
.../Function/ConjugateGradientMultiDimensions.cpp | 6 +
src/Bpp/Numeric/Function/DownhillSimplexMethod.h | 7 +-
src/Bpp/Numeric/Function/Functions.h | 22 +-
src/Bpp/Numeric/Function/MetaOptimizer.h | 4 -
.../Function/OneDimensionOptimizationTools.cpp | 8 +
.../Numeric/Function/Operators/BinaryOperator.h | 168 +++
.../Numeric/Function/Operators/ComputationTree.cpp | 213 ++++
.../Numeric/Function/Operators/ComputationTree.h | 113 ++
.../Function/Operators/ConstantOperator.h} | 92 +-
.../Numeric/Function/Operators/FunctionOperator.h | 133 ++
src/Bpp/Numeric/Function/Operators/MathOperator.h | 138 ++
.../Function/Operators/Operator.h} | 68 +-
.../Numeric/Function/OptimizationStopCondition.h | 14 +-
src/Bpp/Numeric/Function/Optimizer.h | 4 -
.../Function/ReparametrizationFunctionWrapper.h | 12 -
.../Function/ThreePointsNumericalDerivative.cpp | 6 +-
.../Numeric/Hmm/AbstractHmmTransitionMatrix.cpp | 45 +
src/Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.h | 12 +
.../Hmm/AutoCorrelationTransitionMatrix.cpp | 2 +-
src/Bpp/Numeric/Hmm/FullHmmTransitionMatrix.cpp | 19 +-
src/Bpp/Numeric/Hmm/HmmLikelihood.h | 9 +-
src/Bpp/Numeric/Hmm/LogsumHmmLikelihood.cpp | 165 ++-
src/Bpp/Numeric/Hmm/LogsumHmmLikelihood.h | 139 +-
.../Numeric/Hmm/LowMemoryRescaledHmmLikelihood.cpp | 9 +
.../Numeric/Hmm/LowMemoryRescaledHmmLikelihood.h | 39 +-
src/Bpp/Numeric/Hmm/RescaledHmmLikelihood.cpp | 68 +-
src/Bpp/Numeric/Hmm/RescaledHmmLikelihood.h | 25 +-
src/Bpp/Numeric/Matrix/Matrix.h | 9 +-
src/Bpp/Numeric/Matrix/MatrixTools.h | 211 ++--
src/Bpp/Numeric/Number.h | 1 +
src/Bpp/Numeric/Parameter.h | 21 +-
src/Bpp/Numeric/ParameterAliasable.h | 10 +-
src/Bpp/Numeric/ParameterList.cpp | 158 ++-
src/Bpp/Numeric/ParameterList.h | 52 +-
src/Bpp/Numeric/ParametrizableCollection.h | 26 +
src/Bpp/Numeric/Prob/DiscreteDistribution.h | 2 -
src/Bpp/Numeric/Prob/GammaDiscreteDistribution.cpp | 18 +-
src/Bpp/Numeric/Prob/GammaDiscreteDistribution.h | 17 +-
.../Numeric/Prob/MixtureOfDiscreteDistributions.h | 4 -
.../Numeric/Prob/MultipleDiscreteDistribution.h | 2 -
src/Bpp/Numeric/Prob/Simplex.cpp | 6 +-
src/Bpp/Numeric/Prob/Simplex.h | 7 +-
src/Bpp/Numeric/Random/RandomTools.cpp | 19 -
src/Bpp/Numeric/Random/RandomTools.h | 15 +-
src/Bpp/Numeric/Range.h | 24 +
src/Bpp/Numeric/Stat/ContingencyTableTest.h | 7 +-
src/Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.h | 11 +-
src/Bpp/Numeric/Stat/Mva/DualityDiagram.h | 7 +-
src/Bpp/Numeric/Table.h | 1222 ++++++++++++++++++
src/Bpp/Numeric/TableExceptions.h | 175 +++
src/Bpp/Numeric/VectorTools.h | 95 +-
src/Bpp/Text/KeyvalTools.cpp | 76 +-
src/Bpp/Text/KeyvalTools.h | 23 +-
src/Bpp/Text/StringTokenizer.cpp | 6 -
src/Bpp/Text/StringTokenizer.h | 6 +-
src/Bpp/Text/TextTools.cpp | 18 +-
src/Bpp/Text/TextTools.h | 762 +++++------
src/Bpp/{Graph/BasicONode.cpp => Version.h} | 19 +-
src/CMakeLists.txt | 257 +---
test/CMakeLists.txt | 120 +-
test/test_dAGraphObs.cpp | 159 +++
test/test_graphObs.cpp | 144 +++
test/test_treeGraphObs.cpp | 178 +++
128 files changed, 12728 insertions(+), 3588 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..13d3d06
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+# files to be ignored
+
+BppCore.tag
+CMakeCache.txt
+CMakeFiles
+*.cmake
+Makefile
+html
+install_manifest.txt
+libbpp-core.*
+
+# file to be specifically not ignored by previous rules
+
+!/CTestConfig.cmake
+!/cmake/*
diff --git a/AUTHORS.txt b/AUTHORS.txt
index b59d246..e94402e 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -4,6 +4,7 @@ Nicolas Galtier <galtier at univ-montp2.fr>
Céline Scornavacca <scornava at lirmm.fr>
Laurent Guéguen <gueguen at biomserv.univ-lyon1.fr>
Ania Pawelczyk <ania.pawelczyk at gmail.com>
+François Gindraud <francois.gindraud at gmail.com>
Contributed code to Bio++ was enabled thanks to the following institutions and resources:
@@ -20,3 +21,5 @@ Contributed code to Bio++ was enabled thanks to the following institutions and r
2009 - 2010 Berkeley University (Bastien Boussau)
2010 - Laboratoire BBE - UMR CNRS 5558 Université Lyon 1 (Bastien Boussau)
2008 - Laboratoire BBE - UMR CNRS 5558 Université Lyon 1 (Laurent Guéguen)
+2017 - 2018 Projet GrASP - LabEX Ecofect - Université de Lyon (François Gindraud)
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8950551..986cebf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,28 +1,22 @@
# CMake script for Bio++ Core
-# Author: Sylvain Gaillard and Julien Dutheil
+# Authors:
+# Sylvain Gaillard
+# Julien Dutheil
+# Francois Gindraud (2017)
# Created: 17/09/2010
-# Global parameters
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(bpp-core CXX)
+cmake_minimum_required (VERSION 2.8.11)
+project (bpp-core CXX)
+
+# Compile options
+set (CMAKE_CXX_FLAGS "-std=c++11 -Wall -Weffc++ -Wshadow -Wconversion")
+
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
-SET(CMAKE_CXX_FLAGS "-Wall -Weffc++ -Wshadow -Wconversion")
-IF(NOT NO_VIRTUAL_COV)
- SET(NO_VIRTUAL_COV FALSE CACHE BOOL
- "Disable covariant return type with virtual inheritance, for compilers that do not support it."
- FORCE)
-ENDIF(NOT NO_VIRTUAL_COV)
-
-IF(NO_VIRTUAL_COV)
- MESSAGE("-- Covariant return with virtual inheritance disabled.")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNO_VIRTUAL_COV=1")
-ENDIF(NO_VIRTUAL_COV)
-
# Libtool-like version number
# CURRENT:REVISION:AGE => file.so.(C-A).A.R
# current: The most recent interface number that this library implements.
@@ -31,24 +25,38 @@ ENDIF(NO_VIRTUAL_COV)
# library implements.
# In other words, the library implements all the interface numbers in the
# range from number current - age to current.
-SET(BPPCORE_VERSION_CURRENT "2")
-SET(BPPCORE_VERSION_REVISION "3")
-SET(BPPCORE_VERSION_AGE "0")
+SET(${PROJECT_NAME}_VERSION_CURRENT "2")
+SET(${PROJECT_NAME}_VERSION_REVISION "4")
+SET(${PROJECT_NAME}_VERSION_AGE "0")
# Effective version number computation
-MATH(EXPR BPPCORE_VERSION_MAJOR "${BPPCORE_VERSION_CURRENT} - ${BPPCORE_VERSION_AGE}")
-SET(BPPCORE_VERSION_MINOR ${BPPCORE_VERSION_AGE})
-SET(BPPCORE_VERSION_PATCH ${BPPCORE_VERSION_REVISION})
-SET(BPPCORE_VERSION "${BPPCORE_VERSION_MAJOR}.${BPPCORE_VERSION_MINOR}.${BPPCORE_VERSION_PATCH}")
-
-# Set the CMAKE_PREFIX_PATH for the find_library fonction when using non
-# standard install location
-IF(CMAKE_INSTALL_PREFIX)
- SET(CMAKE_PREFIX_PATH "${CMAKE_INSTALL_PREFIX}" ${CMAKE_PREFIX_PATH})
-ENDIF(CMAKE_INSTALL_PREFIX)
+MATH(EXPR ${PROJECT_NAME}_VERSION_MAJOR "${${PROJECT_NAME}_VERSION_CURRENT} - ${${PROJECT_NAME}_VERSION_AGE}")
+SET(${PROJECT_NAME}_VERSION_MINOR ${${PROJECT_NAME}_VERSION_AGE})
+SET(${PROJECT_NAME}_VERSION_PATCH ${${PROJECT_NAME}_VERSION_REVISION})
+SET(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}")
+
+set (PROJECT_VERSION ${${PROJECT_NAME}_VERSION})
+
+# CMake package
+set (cmake-package-location lib/cmake/${PROJECT_NAME})
+include (CMakePackageConfigHelpers)
+configure_package_config_file (
+ package.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/package.cmake
+ INSTALL_DESTINATION ${cmake-package-location}
+ )
+write_basic_package_version_file (
+ ${CMAKE_CURRENT_BINARY_DIR}/package-version.cmake
+ VERSION ${PROJECT_VERSION}
+ COMPATIBILITY SameMajorVersion
+ )
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/package.cmake DESTINATION ${cmake-package-location}
+ RENAME ${PROJECT_NAME}-config.cmake)
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/package-version.cmake DESTINATION ${cmake-package-location}
+ RENAME ${PROJECT_NAME}-config-version.cmake)
-# Subdirectories
-ADD_SUBDIRECTORY(src)
+# Define the libraries
+add_subdirectory (src)
# Doxygen
FIND_PACKAGE(Doxygen)
@@ -67,47 +75,22 @@ ENDIF (DOXYGEN_FOUND)
# Packager
SET(CPACK_PACKAGE_NAME "libbpp-core")
SET(CPACK_PACKAGE_VENDOR "Bio++ Development Team")
-SET(CPACK_PACKAGE_VERSION "2.2.0")
+SET(CPACK_PACKAGE_VERSION "2.3.0")
SET(CPACK_PACKAGE_VERSION_MAJOR "2")
-SET(CPACK_PACKAGE_VERSION_MINOR "2")
+SET(CPACK_PACKAGE_VERSION_MINOR "3")
SET(CPACK_PACKAGE_VERSION_PATCH "0")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Bio++ Core library")
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING.txt")
SET(CPACK_RESOURCE_FILE_AUTHORS "${CMAKE_SOURCE_DIR}/AUTHORS.txt")
SET(CPACK_RESOURCE_FILE_INSTALL "${CMAKE_SOURCE_DIR}/INSTALL.txt")
SET(CPACK_SOURCE_GENERATOR "TGZ")
-SET(CPACK_SOURCE_IGNORE_FILES
- "CMakeFiles"
- "Makefile"
- "_CPack_Packages"
- "CMakeCache.txt"
- ".*\\\\.cmake"
- ".*\\\\.git"
- ".*\\\\.gz"
- ".*\\\\.deb"
- ".*\\\\.rpm"
- ".*\\\\.dmg"
- ".*\\\\..*\\\\.swp"
- "src/\\\\..*"
- "src/libbpp*"
- "debian/tmp"
- "debian/libbpp.*/"
- "debian/libbpp.*\\\\.so.*"
- "debian/libbpp.*\\\\.a"
- "debian/libbpp.*\\\\.substvars"
- "debian/libbpp.*\\\\.debhelper"
- "debian/debhelper\\\\.log"
- "html"
- "Core.tag"
- "Testing"
- "build-stamp"
- "install_manifest.txt"
- "DartConfiguration.tcl"
- ${CPACK_SOURCE_IGNORE_FILES}
-)
-IF (MACOS)
- SET(CPACK_GENERATOR "Bundle")
-ENDIF()
+# /!\ This assumes that an external build is used
+SET(CPACK_SOURCE_IGNORE_FILES
+ "/build/"
+ "/\\\\.git/"
+ "/\\\\.gitignore"
+ ${CPACK_SOURCE_IGNORE_FILES}
+ )
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
SET(CPACK_DEBSOURCE_PACKAGE_FILE_NAME "lib${CMAKE_PROJECT_NAME}_${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}.orig")
@@ -115,21 +98,8 @@ INCLUDE(CPack)
#This adds the 'dist' target
ADD_CUSTOM_TARGET(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
-# 'clean' is not (yet) a first class target. However, we need to clean the directories before building the sources:
-IF("${CMAKE_GENERATOR}" MATCHES "Make")
- ADD_CUSTOM_TARGET(make_clean
- COMMAND ${CMAKE_MAKE_PROGRAM} clean
- WORKING_DIRECTORY ${CMAKE_CURRENT_DIR}
- )
- ADD_DEPENDENCIES(dist make_clean)
-ENDIF()
IF (UNIX)
-#This creates deb packages:
-ADD_CUSTOM_TARGET(origdist COMMAND cp ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz ../${CPACK_DEBSOURCE_PACKAGE_FILE_NAME}.tar.gz)
-ADD_DEPENDENCIES(origdist dist)
-ADD_CUSTOM_TARGET(deb dpkg-buildpackage -uc -us -i${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz)
-ADD_DEPENDENCIES(deb origdist)
#This creates rpm packages:
ADD_CUSTOM_TARGET(rpm rpmbuild -ta ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz)
@@ -141,8 +111,9 @@ SET(CTEST_UPDATE_TYPE git)
SET(UPDATE_COMMAND "git")
SET(UPDATE_OPTIONS "")
-ENABLE_TESTING()
-INCLUDE(CTest)
-IF (BUILD_TESTING)
- ADD_SUBDIRECTORY(test)
-ENDIF(BUILD_TESTING)
+# Tests
+enable_testing ()
+include (CTest)
+if (BUILD_TESTING)
+ add_subdirectory (test)
+endif (BUILD_TESTING)
diff --git a/CTestConfig.cmake b/CTestConfig.cmake
new file mode 100644
index 0000000..9a54c4e
--- /dev/null
+++ b/CTestConfig.cmake
@@ -0,0 +1,13 @@
+## This file should be placed in the root directory of your project.
+## Then modify the CMakeLists.txt file in the root directory of your
+## project to incorporate the testing dashboard.
+## # The following are required to uses Dart and the Cdash dashboard
+## ENABLE_TESTING()
+## INCLUDE(CTest)
+set(CTEST_PROJECT_NAME "bpp-core")
+set(CTEST_NIGHTLY_START_TIME "00:00:00 CEST")
+
+set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_SITE "biopp.univ-montp2.fr")
+set(CTEST_DROP_LOCATION "/dashboard/submit.php?project=bpp-core")
+set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/ChangeLog b/ChangeLog
index 26b8901..5d4ff6f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+10/0(/17 -*- Version 2.3.0 -*-
+
+26/04/16 Julien Dutheil
+* Upgrading to C++11
+
+10/07/14 Thomas Bigot
+* New graph structures
+
17/09/14 -*- Version 2.2.0 -*-
16/09/14 Julien Dutheil
diff --git a/Doxyfile b/Doxyfile
index 75bf108..df39478 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -1,4 +1,4 @@
-# Doxyfile 1.8.6
+# Doxyfile 1.8.11
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -38,7 +38,7 @@ PROJECT_NAME = bpp-core
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = 2.2.0
+PROJECT_NUMBER = 2.3.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -46,10 +46,10 @@ PROJECT_NUMBER = 2.2.0
PROJECT_BRIEF =
-# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
-# the documentation. The maximum height of the logo should not exceed 55 pixels
-# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
-# to the output directory.
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
PROJECT_LOGO =
@@ -60,7 +60,7 @@ PROJECT_LOGO =
OUTPUT_DIRECTORY =
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
@@ -70,6 +70,14 @@ OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
@@ -85,14 +93,14 @@ CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
@@ -127,7 +135,7 @@ ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = YES
-# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
@@ -197,9 +205,9 @@ MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
-# new page for each member. If set to NO, the documentation of a member will be
-# part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
@@ -261,11 +269,14 @@ OPTIMIZE_OUTPUT_VHDL = NO
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
-# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C.
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
#
-# Note For files without extension you can use no_extension as a placeholder.
+# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
@@ -284,8 +295,8 @@ MARKDOWN_SUPPORT = YES
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
-# or globally by setting AUTOLINK_SUPPORT to NO.
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
@@ -325,13 +336,20 @@ SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
+# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
@@ -390,7 +408,7 @@ LOOKUP_CACHE_SIZE = 0
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
@@ -400,35 +418,35 @@ LOOKUP_CACHE_SIZE = 0
EXTRACT_ALL = YES
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = YES
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
-# This flag is only useful for Objective-C code. When set to YES local methods,
+# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO only methods in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
@@ -453,21 +471,21 @@ HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO these classes will be included in the various overviews. This option has
-# no effect if EXTRACT_ALL is enabled.
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO these declarations will be
+# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO these
+# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
@@ -481,7 +499,7 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES upper-case letters are also
+# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
@@ -490,12 +508,19 @@ INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES the
+# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
@@ -523,14 +548,14 @@ INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order. Note that
+# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
@@ -575,27 +600,25 @@ SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
-# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
-# todo list. This list is created by putting \todo commands in the
-# documentation.
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = YES
-# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
-# test list. This list is created by putting \test commands in the
-# documentation.
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = NO
-# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = NO
-# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
@@ -620,8 +643,8 @@ ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES the list
-# will mention the files that were used to generate the documentation.
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
@@ -669,8 +692,7 @@ LAYOUT_FILE =
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
-# search path. Do not use file names with spaces, bibtex cannot handle them. See
-# also \cite for info how to create references.
+# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
@@ -686,7 +708,7 @@ CITE_BIB_FILES =
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
@@ -694,7 +716,7 @@ QUIET = NO
WARNINGS = YES
-# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
@@ -711,12 +733,18 @@ WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
-# value. If set to NO doxygen will only warn about wrong or incomplete parameter
-# documentation, but not about the absence of documentation.
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
# The default value is: NO.
WARN_NO_PARAMDOC = NO
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
@@ -740,7 +768,7 @@ WARN_LOGFILE =
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
-# spaces.
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = src
@@ -756,12 +784,17 @@ INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank the
-# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
-# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
-# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
-# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
-# *.qsf, *.as and *.js.
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
+# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
FILE_PATTERNS = *.h \
*.cpp
@@ -848,6 +881,10 @@ IMAGE_PATH =
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
INPUT_FILTER =
@@ -857,11 +894,15 @@ INPUT_FILTER =
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER ) will also be used to filter the input files that are used for
+# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
@@ -921,7 +962,7 @@ REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
@@ -968,6 +1009,25 @@ USE_HTAGS = NO
VERBATIM_HEADERS = YES
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse-libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
@@ -998,7 +1058,7 @@ IGNORE_PREFIX =
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = YES
@@ -1060,13 +1120,15 @@ HTML_FOOTER =
HTML_STYLESHEET =
-# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
-# defined cascading style sheet that is included after the standard style sheets
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefor more robust against future updates.
-# Doxygen will copy the style sheet file to the output directory. For an example
-# see the documentation.
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
@@ -1082,7 +1144,7 @@ HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the stylesheet and background images according to
+# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
@@ -1113,8 +1175,9 @@ HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: YES.
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES
@@ -1210,28 +1273,29 @@ GENERATE_HTMLHELP = NO
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
-# The GENERATE_CHI flag controls if a separate .chi index file is generated (
-# YES) or that it should be included in the master .chm file ( NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# The BINARY_TOC flag controls whether a binary table of contents is generated (
-# YES) or a normal table of contents ( NO) in the .chm file.
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1344,7 +1408,7 @@ DISABLE_INDEX = NO
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
@@ -1372,7 +1436,7 @@ ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1401,7 +1465,7 @@ FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# http://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
@@ -1471,11 +1535,11 @@ SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
-# are two flavours of web server based searching depending on the
-# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
-# searching and an index file used by the script. When EXTERNAL_SEARCH is
-# enabled the indexing and searching needs to be provided by external tools. See
-# the section "External Indexing and Searching" for details.
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
@@ -1487,7 +1551,7 @@ SERVER_BASED_SEARCH = NO
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/).
#
@@ -1500,7 +1564,7 @@ EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/). See the section "External Indexing and
# Searching" for details.
@@ -1538,7 +1602,7 @@ EXTRA_SEARCH_MAPPINGS =
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
@@ -1569,7 +1633,7 @@ LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
@@ -1587,9 +1651,12 @@ COMPACT_LATEX = NO
PAPER_TYPE = a4wide
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. To get the times font for
-# instance you can specify
-# EXTRA_PACKAGES=times
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1603,23 +1670,36 @@ EXTRA_PACKAGES = amsmath
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
-# replace them by respectively the title of the page, the current date and time,
-# only the current date, the version number of doxygen, the project name (see
-# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer.
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
@@ -1637,8 +1717,8 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = NO
-# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1679,11 +1759,19 @@ LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
@@ -1698,7 +1786,7 @@ GENERATE_RTF = NO
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
@@ -1735,11 +1823,21 @@ RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
@@ -1763,6 +1861,13 @@ MAN_OUTPUT = man
MAN_EXTENSION = .3
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
@@ -1776,7 +1881,7 @@ MAN_LINKS = NO
# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
@@ -1790,19 +1895,7 @@ GENERATE_XML = NO
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_DTD =
-
-# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
@@ -1815,7 +1908,7 @@ XML_PROGRAMLISTING = YES
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
-# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
@@ -1829,14 +1922,23 @@ GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
-# Definitions (see http://autogen.sf.net) file that captures the structure of
-# the code including all documentation. Note that this feature is still
-# experimental and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
@@ -1845,7 +1947,7 @@ GENERATE_AUTOGEN_DEF = NO
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
@@ -1853,7 +1955,7 @@ GENERATE_AUTOGEN_DEF = NO
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
@@ -1861,9 +1963,9 @@ GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO the
+# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
@@ -1883,14 +1985,14 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
-# in the source code. If set to NO only conditional compilation will be
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
@@ -1906,7 +2008,7 @@ MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@@ -1948,9 +2050,9 @@ PREDEFINED =
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
-# remove all refrences to function-like macros that are alone on a line, have an
-# all uppercase name, and do not end with a semicolon. Such function macros are
-# typically used for boiler-plate code, and will confuse the parser if not
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@@ -1970,7 +2072,7 @@ SKIP_FUNCTION_MACROS = YES
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
-# Note: Each tag file must have an unique name (where the name does NOT include
+# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
@@ -1982,20 +2084,21 @@ TAGFILES =
GENERATE_TAGFILE = BppCore.tag
-# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
-# class index. If set to NO only the inherited external classes will be listed.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
# The default value is: NO.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
-# the modules index. If set to NO, only the current project's groups will be
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = YES
-# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
@@ -2012,7 +2115,7 @@ PERL_PATH = /usr/bin/perl
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
@@ -2037,7 +2140,7 @@ MSCGEN_PATH =
DIA_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
@@ -2048,7 +2151,7 @@ HIDE_UNDOC_RELATIONS = YES
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
-# The default value is: NO.
+# The default value is: YES.
HAVE_DOT = YES
@@ -2062,7 +2165,7 @@ HAVE_DOT = YES
DOT_NUM_THREADS = 0
-# When you want a differently looking font n the dot files that doxygen
+# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
@@ -2110,7 +2213,7 @@ COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
@@ -2162,7 +2265,8 @@ INCLUDED_BY_GRAPH = YES
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2173,7 +2277,8 @@ CALL_GRAPH = NO
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command.
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2196,11 +2301,17 @@ GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot.
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
-# Possible values are: png, jpg, gif and svg.
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2243,6 +2354,19 @@ MSCFILE_DIRS =
DIAFILE_DIRS =
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
@@ -2279,7 +2403,7 @@ MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
@@ -2296,7 +2420,7 @@ DOT_MULTI_TARGETS = YES
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# files that are used to generate the various graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
diff --git a/INSTALL.txt b/INSTALL.txt
index c8859da..8c499db 100644
--- a/INSTALL.txt
+++ b/INSTALL.txt
@@ -1,12 +1,23 @@
-This software needs cmake >= 2.6 to build.
+This software needs cmake >= 2.8.11 and a C++11 capable compiler to build
After installing cmake, run it with the following command:
-cmake -DCMAKE_INSTALL_PREFIX=[where to install, for instance /usr/local or $HOME/.local] .
+$ cmake -DCMAKE_INSTALL_PREFIX=[where to install, for instance /usr/local or $HOME/.local] .
If available, you can also use ccmake instead of cmake for a more user-friendly interface.
-Then compile and install the software with
-make install
+Then compile and install the software with:
+$ make install
You may also consider installing and using the software checkinstall for easier system administration.
+If you install Bio++ in a non standard path (not /usr/), remember that:
+-> if you compile your project with CMake, give it the path with -DCMAKE_PREFIX_PATH=<path>
+-> if you compile with something else, give the path to the compiler (-I / -L options)
+-> if you use shared libraries, you must also tell programs where to find them at startup:
+ -> either by adding the path to LD_LIBRARY_PATH environment variable.
+ -> or by using RPATHs to hard code the path in the executable (generates NON PORTABLE executables !)
+ -> with CMake, see documentation in bpp-core/cmake/project-template
+ -> or see your compiler documentation ("-Wl,-rpath,<path>" for clang/gcc)
+ -> consider installing Bio++ with the "-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE" option
+
+Detailed documentation for using Bio++ with CMake are available in bpp-core/cmake/
diff --git a/bpp-core.spec b/bpp-core.spec
index 38b3761..68fdcb6 100644
--- a/bpp-core.spec
+++ b/bpp-core.spec
@@ -1,5 +1,5 @@
%define _basename bpp-core
-%define _version 2.2.0
+%define _version 2.3.0
%define _release 1
%define _prefix /usr
@@ -15,8 +15,8 @@ Summary: Bio++ Core library
Group: Development/Libraries/C and C++
BuildRoot: %{_builddir}/%{_basename}-root
-BuildRequires: cmake >= 2.6.0
-BuildRequires: gcc-c++ >= 4.0.0
+BuildRequires: cmake >= 2.8.11
+BuildRequires: gcc-c++ >= 4.7.0
AutoReq: yes
AutoProv: yes
@@ -59,100 +59,8 @@ rm -rf $RPM_BUILD_ROOT
%post -n libbpp-core2 -p /sbin/ldconfig
-%post -n libbpp-core-devel
-createGeneric() {
- echo "-- Creating generic include file: $1.all"
- #Make sure we run into subdirectories first:
- dirs=()
- for file in "$1"/*
- do
- if [ -d "$file" ]
- then
- # Recursion:
- dirs+=( "$file" )
- fi
- done
- for dir in ${dirs[@]}
- do
- createGeneric $dir
- done
- #Now list all files, including newly created .all files:
- if [ -f $1.all ]
- then
- rm $1.all
- fi
- dir=`basename $1`
- for file in "$1"/*
- do
- if [ -f "$file" ] && ( [ "${file##*.}" == "h" ] || [ "${file##*.}" == "all" ] )
- then
- file=`basename $file`
- echo "#include \"$dir/$file\"" >> $1.all
- fi
- done;
-}
-# Actualize .all files
-createGeneric %{_prefix}/include/Bpp
-exit 0
-
-%preun -n libbpp-core-devel
-removeGeneric() {
- if [ -f $1.all ]
- then
- echo "-- Remove generic include file: $1.all"
- rm $1.all
- fi
- for file in "$1"/*
- do
- if [ -d "$file" ]
- then
- # Recursion:
- removeGeneric $file
- fi
- done
-}
-# Actualize .all files
-removeGeneric %{_prefix}/include/Bpp
-exit 0
-
%postun -n libbpp-core2 -p /sbin/ldconfig
-%postun -n libbpp-core-devel
-createGeneric() {
- echo "-- Creating generic include file: $1.all"
- #Make sure we run into subdirectories first:
- dirs=()
- for file in "$1"/*
- do
- if [ -d "$file" ]
- then
- # Recursion:
- dirs+=( "$file" )
- fi
- done
- for dir in ${dirs[@]}
- do
- createGeneric $dir
- done
- #Now list all files, including newly created .all files:
- if [ -f $1.all ]
- then
- rm $1.all
- fi
- dir=`basename $1`
- for file in "$1"/*
- do
- if [ -f "$file" ] && ( [ "${file##*.}" == "h" ] || [ "${file##*.}" == "all" ] )
- then
- file=`basename $file`
- echo "#include \"$dir/$file\"" >> $1.all
- fi
- done;
-}
-# Actualize .all files
-createGeneric %{_prefix}/include/Bpp
-exit 0
-
%files -n libbpp-core2
%defattr(-,root,root)
%doc AUTHORS.txt COPYING.txt INSTALL.txt ChangeLog
@@ -161,11 +69,17 @@ exit 0
%files -n libbpp-core-devel
%defattr(-,root,root)
%doc AUTHORS.txt COPYING.txt INSTALL.txt ChangeLog
+%dir %{_prefix}/lib/cmake/
+%dir %{_prefix}/lib/cmake/bpp-core
%{_prefix}/%{_lib}/lib*.so
%{_prefix}/%{_lib}/lib*.a
+%{_prefix}/lib/cmake/bpp-core/bpp-core*.cmake
%{_prefix}/include/*
%changelog
+* Wed May 10 2017 Julien Dutheil <julien.dutheil at univ-montp2.fr> 2.3.0-1
+- New graph structures
+- Upgrade to C++11
* Wed Sep 17 2014 Julien Dutheil <julien.dutheil at univ-montp2.fr> 2.2.0-1
- Reparametrization wrapper debugged
- Improved and rationalized display of warning messages
diff --git a/cmake/doc-cmake-for-developpers.cmake b/cmake/doc-cmake-for-developpers.cmake
new file mode 100644
index 0000000..bbae8d1
--- /dev/null
+++ b/cmake/doc-cmake-for-developpers.cmake
@@ -0,0 +1,240 @@
+# Documentation of the CMake system of Bio++
+# Authors:
+# Francois Gindraud (2017)
+# Created: 10/03/2017
+
+# This file describes the CMake setup of bio++ (for this component and others).
+# It includes important parts from cmake files and comments them.
+# Not described: cpack, doxygen
+
+####################################################################################################
+# Main CMakeLists.txt
+####################################################################################################
+
+cmake_minimum_required (VERSION 2.8.11)
+# 2.8.11 is required for:
+# - clean target properties (link, include dir)
+
+project (bpp-something CXX)
+# Defines a lot of stuff including PROJECT_NAME which will contain "bpp-something"
+# PROJECT_NAME is used to name:
+# - the library
+# - the CMake targets (${PROJECT_NAME}-static or ${PROJECT_NAME}-shared)
+# - the CMake package
+# Do not change it unless there is a good reason...
+
+set (CMAKE_CXX_FLAGS "std=c++11 -Wall -Weffc++ -Wshadow -Wconversion")
+# Define compile options to be used for all C++ targets.
+# NOTES for the future:
+# -> CMake >= 2.8.12 adds per target COMPILE_OPTIONS by using target_compile_options (<target> [PRIVATE|PUBLIC] <opt1> ... <optN>)
+# -> CMake >= 3.1.x provides a CXX_STANDARD variable to set -std=...
+# -> It also provides a "feature" property on targets which annotates, and auto selects the right -std=...
+
+SET(${PROJECT_NAME}_VERSION_CURRENT "2")
+SET(${PROJECT_NAME}_VERSION_REVISION "3")
+SET(${PROJECT_NAME}_VERSION_AGE "0")
+MATH(EXPR ${PROJECT_NAME}_VERSION_MAJOR "${${PROJECT_NAME}_VERSION_CURRENT} - ${${PROJECT_NAME}_VERSION_AGE}")
+SET(${PROJECT_NAME}_VERSION_MINOR ${${PROJECT_NAME}_VERSION_AGE})
+SET(${PROJECT_NAME}_VERSION_PATCH ${${PROJECT_NAME}_VERSION_REVISION})
+SET(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}")
+# Libtool-like version number
+# CURRENT:REVISION:AGE => file.so.(C-A).A.R
+# current: The most recent interface number that this library implements.
+# revision: The implementation number of the current interface.
+# age: The difference between the newest and oldest interfaces that this
+# library implements.
+# In other words, the library implements all the interface numbers in the
+# range from number current - age to current.
+# NOTE: unchanged from old cmake.
+
+set (PROJECT_VERSION ${${PROJECT_NAME}_VERSION})
+# Sets PROJECT_VERSION, which is used in package template files (version and config).
+# NOTE: CMake >= 3.0 adds a "VERSION x.y.z" parameter to project() that fills these variables automatically (major/minor/...).
+
+if (CMAKE_INSTALL_PREFIX)
+ set (CMAKE_PREFIX_PATH "${CMAKE_INSTALL_PREFIX}" ${CMAKE_PREFIX_PATH})
+endif (CMAKE_INSTALL_PREFIX)
+find_package (bpp-neededcomponent x.y.z REQUIRED)
+# Includes other needed bpp components.
+# They must be installed to standard paths, or to the target install path (hence the search path addition).
+# If a version is provided, it will check that the found component is version-compatible with what we requested.
+# -> Detects when we link to an old bpp version.
+# Internally, this executes the package files of the needed components if they are found.
+#
+# Package files will include their targets file that define "imported targets".
+# using target_link_libraries (current_target bpp-neededcomponent-static) will add link, include, and compile option flags to the whole compilation.
+# For convenience package files also define the BPP_LIBS_SHARED and BPP_LIBS_STATIC variables.
+# These variables hold a list of all imported shared or static library targets of bpp.
+
+set (cmake-package-location lib/cmake/${PROJECT_NAME})
+# Place where cmake package and target files will be placed at install.
+# This is one of the paths that find_package will check, others are possible, see find_package().
+
+include (CMakePackageConfigHelpers)
+# Standard CMake module defining configure_package_config_file and write_basic_package_version_file.
+
+configure_package_config_file (
+ package.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/package.cmake
+ INSTALL_DESTINATION ${cmake-package-location}
+ )
+# Generates the CMake package file from the template package.cmake.in
+# It performs variable substitutions to fill the template with project name and versions.
+
+write_basic_package_version_file (
+ ${CMAKE_CURRENT_BINARY_DIR}/package-version.cmake
+ VERSION ${PROJECT_VERSION}
+ COMPATIBILITY SameMajorVersion
+ )
+# Generates a CMake package version file. Used by find_package to check version numbers.
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/package.cmake DESTINATION ${cmake-package-location}
+ RENAME ${PROJECT_NAME}-config.cmake)
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/package-version.cmake DESTINATION ${cmake-package-location}
+ RENAME ${PROJECT_NAME}-config-version.cmake)
+# Install the cmake package files.
+# They are renamed to the name convention required by CMake.
+
+add_subdirectory (src)
+# Define the library targets.
+
+enable_testing ()
+include (CTest)
+if (BUILD_TESTING)
+ add_subdirectory (test)
+endif (BUILD_TESTING)
+# Include tests.
+
+####################################################################################################
+# src/CMakeLists.txt
+# Defines library targets (using PROJECT_NAME heavily, to be as generic as possible).
+####################################################################################################
+
+set (CPP_FILES
+ Bpp/Something/do_something.cpp
+ ...
+ )
+# File list (sorted to easily find duplicates or missing)
+
+add_library (${PROJECT_NAME}-static STATIC ${CPP_FILES})
+# Define the static lib
+
+target_include_directories (${PROJECT_NAME}-static PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>
+ )
+# Annotates the static lib target with include paths.
+# These paths will be added as -I options:
+# - during compilation of the target, by looking at CMAKE_CURRENT_SOURCE_DIR
+# - during compilation of anything that links to this target, by looking at <install_dir>/include.
+# This allow the code to reference headers by a path relative to src/ instead of using ../OtherDir/blah.h
+# NOTE the "$<INSTALL_PREFIX>/" part is only needed to support 2.8.11 due to a bugged cmake check.
+
+set_target_properties (${PROJECT_NAME}-static PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
+# Set target file name (default is the target name)
+
+target_link_libraries (${PROJECT_NAME}-static ${BPP_LIBS_STATIC})
+# "Links" to all bpp components included by find_package (adds everything, -I, -L -lbpp-comps...)
+# (a manual list of bpp components targets also works here).
+
+add_library (${PROJECT_NAME}-shared SHARED ${CPP_FILES})
+target_include_directories (${PROJECT_NAME}-shared PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ $<INSTALL_INTERFACE:include>
+ )
+set_target_properties (${PROJECT_NAME}-shared
+ PROPERTIES OUTPUT_NAME ${PROJECT_NAME}
+ MACOSX_RPATH 1
+ VERSION ${${PROJECT_NAME}_VERSION}
+ SOVERSION ${${PROJECT_NAME}_VERSION_MAJOR}
+ )
+target_link_libraries (${PROJECT_NAME}-shared ${BPP_LIBS_SHARED})
+target_compile_options (${PROJECT_NAME}-shared
+ PUBLIC ${public-compile-options}
+ PRIVATE ${private-compile-options}
+ )
+# Build the shared lib, using the same system
+
+install (
+ TARGETS ${PROJECT_NAME}-static ${PROJECT_NAME}-shared
+ EXPORT ${PROJECT_NAME}-targets
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX}
+ )
+# Install libraries, while recording them under "${PROJECT_NAME}-targets"
+
+install (
+ DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Bpp
+ DESTINATION include
+ FILES_MATCHING PATTERN "*.h"
+ )
+# Install headers (using the sub Bpp dir avoids looking into CMake temporary internal dirs in case of in tree build).
+
+install (EXPORT ${PROJECT_NAME}-targets DESTINATION ${cmake-package-location})
+# Install the target export file, that defines "imported targets" with properties for the two libs.
+
+####################################################################################################
+# bpp-something-config.cmake.in
+# CMake package file template, will be expanded into a valid cmake file by configure_package_config_file()
+####################################################################################################
+
+ at PACKAGE_INIT@
+# Boilerplate from CMake (I do not think this is required in our case, but they say its better to use it).
+
+if (NOT @PROJECT_NAME at _FOUND)
+# Protection against double include of this package.
+
+find_package (bpp-core @bpp-core_VERSION@ REQUIRED)
+# Find dependencies.
+# bpp-core_VERSION is a variable defined in main CMakeLists to the version of the found bpp-core component.
+# @bpp-core_VERSION@ will be replaced by the version that was found.
+# Thus, after installation, this package of bpp-something we require the same version.
+
+include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME at -targets.cmake")
+# Include the imported targets
+
+set (BPP_LIBS_STATIC "${BPP_LIBS_STATIC}" @PROJECT_NAME at -static)
+set (BPP_LIBS_SHARED "${BPP_LIBS_SHARED}" @PROJECT_NAME at -shared)
+# Append targets to convenient lists
+
+get_property (static-location TARGET @PROJECT_NAME at -static PROPERTY LOCATION)
+get_property (shared-location TARGET @PROJECT_NAME at -shared PROPERTY LOCATION)
+get_property (header-location TARGET @PROJECT_NAME at -static PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
+message (STATUS "@PROJECT_NAME@ @PROJECT_VERSION@ found:")
+message (STATUS " static lib: ${static-location}")
+message (STATUS " shared lib: ${shared-location}")
+message (STATUS " includes: ${header-location}")
+unset (static-location)
+unset (shared-location)
+unset (header-location)
+# Print information about this package when included (version, paths of libs and includes).
+
+endif (NOT @PROJECT_NAME at _FOUND)
+
+####################################################################################################
+# test.CMakeLists.txt
+# Performs tests
+####################################################################################################
+
+file (GLOB test_cpp_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
+# Each .cpp file in test/ is considered to be a test.
+# Globbing is more error prone than an explicit list, but tests are not critical.
+# This allow tests to be added without having to modify the CMakelist (just re-run cmake).
+
+foreach (test_cpp_file ${test_cpp_files})
+ get_filename_component (test_name ${test_cpp_file} NAME_WE)
+ add_executable (${test_name} ${test_cpp_file})
+ # Each test is named after the cpp file without extension.
+
+ target_link_libraries (${test_name} ${PROJECT_NAME}-shared)
+ # Link to bpp-something shared library (pulls required -I -L -lbpp-*).
+
+ add_test (
+ NAME ${test_name}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMAND ${test_name}
+ )
+ # Add test to "make test".
+ # The command must return EXIT_SUCCESS (usually 0) to be considered successful.
+ # Test is run explicitely in CMAKE_CURRENT_SOURCE_DIR to allow out of tree builds (find data files).
+endforeach (test_cpp_file)
diff --git a/cmake/project-template-for-users.cmake b/cmake/project-template-for-users.cmake
new file mode 100644
index 0000000..6fd957a
--- /dev/null
+++ b/cmake/project-template-for-users.cmake
@@ -0,0 +1,106 @@
+# Template project file to compile a program with Bio++ libraries
+# Authors:
+# Francois Gindraud (2017)
+# Created: 21/04/2017
+
+# This file gives an example of how to compile your program using CMake and Bio++.
+# Do not just copy the file as is, but use it as a guideline for your own project.
+# If just copied and rename into place, some commands in section ADVANCED will interfere with the BASIC config.
+# Remember that to be processed by CMake, the project file must be named "CMakeLists.txt".
+
+################################### BASIC ####################################
+# This is a basic configuration for users with Bio++ libraries installed in a standard system place (/usr/).
+
+# These two lines are CMake boilerplate
+cmake_minimum_required (VERSION 2.8.11) # Test of version. 2.8.11 is the oldest version supported by Bio++
+project (myproject CXX) # The name is not critical
+
+# Find Bio++ libraries and import their configurations.
+find_package (bpp-core)
+find_package (bpp-seq)
+
+# Bio++ REQUIRES using at least the C++11 standard.
+# This line specifies options passed to the compiler (you can add your own).
+set (CMAKE_CXX_FLAGS "-std=c++11")
+
+# Tells CMake to create a binary from dummy.cpp (replace with your .cpp file(s))
+add_executable (myprogram dummy.cpp other.cpp)
+
+# Link with the shared libraries of Bio++
+target_link_libraries (myprogram ${BPP_LIBS_SHARED})
+
+# You can then compile your program with:
+# $ cmake .
+# $ make
+
+################################# ADVANCED ###################################
+# Here we give some more advanced details
+
+### Out of tree advice:
+# CMake supports what is called "out of tree build":
+# $ mkdir build
+# $ cd build
+# $ cmake <options> ..
+# $ make
+# In this form, you can easily delete all CMake stuff and generated files by deleting the build/ dir.
+# It can be useful if you want to be sure to recompile from a clean state.
+
+### find_package(bpp-<module>):
+#
+# If Bio++ is installed in a non standard path, CMake MUST be told to look there for it to find the Bio++ libraries.
+# This can be done with: $ cmake -DCMAKE_PREFIX_PATH=<bpp-location> .
+#
+# find_package(bpp-<module>) defines, if successful:
+# - a bpp-<module>-static symbol to link with the static library
+# - a bpp-<module>-shared symbol to link with the shared library
+# - variables BPP_LIBS_SHARED and BPP_LIBS_STATIC that includes the related symbols and symbols of Bio++ dependencies.
+# The bpp-<module>-{static/shared} symbols also force CMake to link to their Bio++ dependencies.
+# find_package of a a module also does a find_package of dependency Bio++ modules.
+#
+# So, for bpp-phyl (which depends on bpp-seq and bpp-core):
+find_package (bpp-phyl)
+# Is equivalent to:
+find_package (bpp-core)
+find_package (bpp-seq)
+find_package (bpp-phyl)
+# And the following target_link_libraries commands are equivalent:
+target_link_libraries (myprogram bpp-phyl-shared)
+target_link_libraries (myprogram bpp-core-shared bpp-seq-shared bpp-phyl-shared)
+target_link_libraries (myprogram ${BPP_LIBS_SHARED})
+# The short form relies on Bio++ inter module dependencies, but they are unlikely to change.
+
+### Static libraries can be linked by using either:
+target_link_libraries (myprogram bpp-phyl-static)
+target_link_libraries (myprogram ${BPP_LIBS_STATIC})
+# They make your binary program self contained (all Bio++ code is included with it).
+# It can be given to people without having them install Bio++.
+# However, the binary will be huge (10 to 100MB depending of which modules are used).
+# Using `$ strip myprogram` can reduce the binary size.
+
+### Shared libraries, RPATH and LD_LIBRARY_PATH:
+# If you installed Bio++ to a NON STANDARD path and use the shared libraries, you might run into problems like:
+# ./myprog: error while loading shared libraries: libbpp-seq.so.9: cannot open shared object file: No such file or directory
+#
+# The problem is that your executable must find the Bio++ shared library before starting.
+# Libraries are normally searched in standard paths (/usr/lib).
+# Two options exist to add a custom search path (to you Bio++ custom install path):
+# - adding the path to the LD_LIBRARY_PATH environment variable.
+# - adding the path as an RPATH entry in the executable 'myprog' itself.
+#
+# LD_LIBRARY_PATH:
+# - does not require modifying the executable.
+# - the executable can be used everywhere as long as the local Bio++ libs are in /usr/lib or in LD_LIBRARY_PATH.
+# - LD_LIBRARY_PATH paths are used by all program to search for their libs (i.e. other commands in the shell).
+#
+# RPATH:
+# - the executable runs without having to tweak LD_LIBRARY_PATH or anything else.
+# - the executable includes hard-coded paths, so it CANNOT BE PUBLISHED as the paths are local to your system.
+# - by default, the executable in the CMake build directory (after 'make') uses RPATH.
+# - by default, "installed" executables (after 'make install') have no RPATH.
+# - You can force the use of RPATH in installed executables with "-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE"
+# - if using RPATHs, consider compiling Bio++ with them by adding "-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE" during installation.
+# - if you need an installed executable (to publish it without RPATH), add an install command:
+install (TARGETS myprogram RUNTIME DESTINATION bin)
+# And run `$ make install` to install it.
+# You can select the location at the configuration step with -DCMAKE_INSTALL_PREFIX=<path>
+# Or at install step with `$ make DESTDIR=<prefix> install`
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index d84c97f..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,46 +0,0 @@
-libbpp-core (2.2.0-1) unstable; urgency=low
-
- * Reparametrization wrapper debugged
- * Improved and rationalized display of warning messages
- * Possibility to set random seed in applications
- * Code checked for compilation with CLang.
-
- -- Julien Dutheil <julien.dutheil at univ-montp2.fr> Wed, 17 Sep 2014 14:00:00 +0100
-
-libbpp-core (2.1.0-1) unstable; urgency=low
-
- * Extended range classes
- * Improved initialization of static members
- * Extended support for BppO.
-
- -- Julien Dutheil <julien.dutheil at univ-montp2.fr> Mon, 04 Mar 2013 10:15:00 +0100
-
-libbpp-core (2.0.3-1) unstable; urgency=low
-
- * New range classes
- * Linear assigment method
- * Improved string tokenizer and text tools.
-
- -- Julien Dutheil <julien.dutheil at univ-montp2.fr> Thu, 09 Feb 2012 13:00:00 +0100
-
-libbpp-core (2.0.2-1) unstable; urgency=low
-
- * RFP: Bio++ -- The Bio++ bioinformatics libraries. (Closes: #616373).
- * Packages are now non-native.
- * More MatrixTools, multivariate analysis classes and several bugs fixed.
-
- -- Julien Dutheil <julien.dutheil at univ-montp2.fr> Thu, 09 Jun 2011 11:00:00 +0100
-
-libbpp-core (2.0.1) unstable; urgency=low
-
- * Fixed missing RColorSet.cpp source file.
-
- -- Julien Dutheil <julien.dutheil at univ-montp2.fr> Mon, 28 Feb 2011 09:00:00 +0100
-
-libbpp-core (2.0.0) unstable; urgency=low
-
- * New package merging old bpp-utils and bpp-numcalc.
- * New source tree.
-
- -- Julien Dutheil <julien.dutheil at univ-montp2.fr> Mon, 07 Feb 2011 09:00:00 +0100
-
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index 7ed6ff8..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-5
diff --git a/debian/control b/debian/control
deleted file mode 100644
index 8d6aa49..0000000
--- a/debian/control
+++ /dev/null
@@ -1,22 +0,0 @@
-Source: libbpp-core
-Section: libs
-Priority: optional
-Maintainer: Loic Dachary <loic at dachary.org>
-Uploaders: Julien Dutheil <julien.dutheil at univ-montp2.fr>
-Build-Depends: debhelper (>= 5), cmake (>= 2.6)
-Standards-Version: 3.9.4
-
-Package: libbpp-core-dev
-Section: libdevel
-Architecture: any
-Depends: libbpp-core2 (= ${binary:Version}), ${misc:Depends}
-Description: Bio++ Core library development files.
- Contains the Bio++ core classes.
-
-Package: libbpp-core2
-Section: libs
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: Bio++ Core library.
- Contains the Bio++ core classes.
-
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index c9da444..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,74 +0,0 @@
-This package was debianized by Julien Dutheil <julien.dutheil at univ-montp2.fr> on
-Wed, 17 Sep 2014 14:00:00 +0100.
-
-It was downloaded from <http://biopp.univ-montp2.fr/Repositories/sources>
-
-Upstream Author:
-
- Julien Dutheil <julien.dutheil at univ-montp2.fr>
-
-Copyright:
-
- Copyright (C) 2014 Bio++ Development Team
-
-License:
-
- This package 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 2 of the License, or
- (at your option) any later version.
-
- This package 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 package; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-On Debian systems, the complete text of the GNU General
-Public License can be found in `/usr/share/common-licenses/GPL'.
-
-The Debian packaging is (C) 2014, Julien Dutheil <julien.dutheil at univ-montp2.fr> and
-is licensed under the GPL, see above.
-
-The provided software is distributed under the CeCILL license:
-
- This software is governed by the CeCILL license under French law and
- abiding by the rules of distribution of free software. You can use,
- modify and/ or redistribute the software under the terms of the CeCILL
- license as circulated by CEA, CNRS and INRIA at the following URL
- "http://www.cecill.info".
-
- As a counterpart to the access to the source code and rights to copy,
- modify and redistribute granted by the license, users are provided only
- with a limited warranty and the software's author, the holder of the
- economic rights, and the successive licensors have only limited
- liability.
-
- In this respect, the user's attention is drawn to the risks associated
- with loading, using, modifying and/or developing or reproducing the
- software by the user in light of its specific status of free software,
- that may mean that it is complicated to manipulate, and that also
- therefore means that it is reserved for developers and experienced
- professionals having in-depth computer knowledge. Users are therefore
- encouraged to load and test the software's suitability as regards their
- requirements in conditions enabling the security of their systems and/or
- data to be ensured and, more generally, to use and operate it in the
- same conditions as regards security.
-
- The fact that you are presently reading this means that you have had
- knowledge of the CeCILL license and that you accept its terms.
-
-The complete text of the license may be found here:
-http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
-
-It contains some code parts from JAMA, a Java Matrix Library,
- developed by jointly by the Mathworks and NIST;
- see http://math.nist.gov/javanumerics/jama,
- and release under the GPL (files Eigenvalue.hand LUDecomposition.h).
-
-Files ContingencyTableGenerator.h (.cpp) are adpated from file rcont.c
- edited by Martin Maechler, Dec 2003, and belonging to the R software,
- distributed under the GPL.
diff --git a/debian/docs b/debian/docs
deleted file mode 100644
index e69de29..0000000
diff --git a/debian/libbpp-core-dev.install b/debian/libbpp-core-dev.install
deleted file mode 100644
index 0f5727e..0000000
--- a/debian/libbpp-core-dev.install
+++ /dev/null
@@ -1,3 +0,0 @@
-debian/tmp/usr/include/*
-debian/tmp/usr/lib/*.a
-debian/tmp/usr/lib/*.so
diff --git a/debian/libbpp-core2.install b/debian/libbpp-core2.install
deleted file mode 100644
index c45ebcf..0000000
--- a/debian/libbpp-core2.install
+++ /dev/null
@@ -1 +0,0 @@
-debian/tmp/usr/lib/lib*.so.*
diff --git a/debian/postinst b/debian/postinst
deleted file mode 100755
index cff89b1..0000000
--- a/debian/postinst
+++ /dev/null
@@ -1,57 +0,0 @@
-#! /bin/bash
-
-# Abort if any command returns an error value
-set -e
-
-createGeneric() {
- echo "-- Creating generic include file: $1.all"
- #Make sure we run into subdirectories first:
- dirs=()
- for file in "$1"/*
- do
- if [ -d "$file" ]
- then
- # Recursion:
- dirs+=( "$file" )
- fi
- done
- for dir in ${dirs[@]}
- do
- createGeneric $dir
- done
- #Now list all files, including newly created .all files:
- if [ -f $1.all ]
- then
- rm $1.all
- fi
- dir=`basename $1`
- for file in "$1"/*
- do
- if [ -f "$file" ] && ( [ "${file##*.}" == "h" ] || [ "${file##*.}" == "all" ] )
- then
- file=`basename $file`
- echo "#include \"$dir/$file\"" >> $1.all
- fi
- done;
-}
-
-case "$1" in
- configure)
- # Actualize .all files
- createGeneric /usr/include/Bpp
- ;;
- abort-upgrade|abort-remove|abort-deconfigure)
- echo "$1"
- ;;
- *)
- echo "postinst called with unknown argument \`\$1'" >&2
- exit 0
- ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/postrm b/debian/postrm
deleted file mode 100755
index 744f8b1..0000000
--- a/debian/postrm
+++ /dev/null
@@ -1,59 +0,0 @@
-#! /bin/bash
-
-# Abort if any command returns an error value
-set -e
-
-createGeneric() {
- echo "-- Creating generic include file: $1.all"
- #Make sure we run into subdirectories first:
- dirs=()
- for file in "$1"/*
- do
- if [ -d "$file" ]
- then
- # Recursion:
- dirs+=( "$file" )
- fi
- done
- for dir in ${dirs[@]}
- do
- createGeneric $dir
- done
- #Now list all files, including newly created .all files:
- if [ -f $1.all ]
- then
- rm $1.all
- fi
- dir=`basename $1`
- for file in "$1"/*
- do
- if [ -f "$file" ] && ( [ "${file##*.}" == "h" ] || [ "${file##*.}" == "all" ] )
- then
- file=`basename $file`
- echo "#include \"$dir/$file\"" >> $1.all
- fi
- done;
-}
-
-case "$1" in
- remove)
- # Automatically added by dh_makeshlibs
- ldconfig
- # Actualize .all files
- createGeneric /usr/include/Bpp
- ;;
- purge|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
- echo $1
- ;;
- *)
- echo "postrm called with unknown argument \`\$1'" >&2
- exit 0
- ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/prerm b/debian/prerm
deleted file mode 100755
index 8fab52e..0000000
--- a/debian/prerm
+++ /dev/null
@@ -1,41 +0,0 @@
-#! /bin/bash
-
-# Abort if any command returns an error value
-set -e
-
-removeGeneric() {
- if [ -f $1.all ]
- then
- echo "-- Remove generic include file: $1.all"
- rm $1.all
- fi
- for file in "$1"/*
- do
- if [ -d "$file" ]
- then
- # Recursion:
- removeGeneric $file
- fi
- done
-}
-
-case "$1" in
- remove|upgrade|deconfigure)
- # Actualize .all files
- removeGeneric /usr/include/Bpp
- ;;
- failed-upgrade)
- echo "$1"
- ;;
- *)
- echo "prerm called with unknown argument \`$1'" >&2
- exit 1
- ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index 34313ef..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-# Sample debian/rules that uses debhelper.
-# This file was originally written by Joey Hess and Craig Small.
-# As a special exception, when this file is copied by dh-make into a
-# dh-make output file, you may use that output file without restriction.
-# This special exception was added by Craig Small in version 0.37 of dh-make.
-
-# 24/01/10 Modification for use with CMake by Julien Dutheil.
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-
-# These are used for cross-compiling and for saving the configure script
-# from having to guess our platform (since we know it already)
-DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
-DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-
-
-CFLAGS = -Wall -g
-
-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
- CFLAGS += -O0
-else
- CFLAGS += -O2
-endif
-
-# shared library versions
-version=`ls src/lib*.so.* | \
- awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
-major=`ls src/lib*.so.* | \
- awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
-
-configure:
- cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTING=OFF .
-
-config.status: configure
- dh_testdir
-
-build: build-arch build-indep
-build-arch: build-stamp
-build-indep: build-stamp
-build-stamp: config.status
- dh_testdir
-
- # Add here commands to compile the package.
- $(MAKE)
-
- touch $@
-
-clean:
- dh_testdir
- dh_testroot
-
- # Add here commands to clean up after the build process.
- [ ! -f Makefile ] || $(MAKE) clean;
- [ ! -f Makefile ] || rm Makefile;
- [ ! -f src/Makefile ] || rm src/Makefile;
- [ ! -f test/Makefile ] || rm test/Makefile;
- rm -f config.sub config.guess
- rm -f build-stamp
- rm -f CMakeCache.txt
- rm -f *.cmake
- rm -f src/*.cmake
- rm -f test/*.cmake
- rm -rf CMakeFiles
- rm -rf src/CMakeFiles
- rm -rf test/CMakeFiles
- rm -rf _CPack_Packages
- rm -rf Testing
- rm -f DartConfiguration.tcl
-
- dh_clean
-
-install: build
- dh_testdir
- dh_testroot
- dh_prep
- dh_installdirs
-
- # Add here commands to install the package into debian/tmp
- $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
-
-
-# Build architecture-independent files here.
-binary-indep: build install
-# We have nothing to do by default.
-
-# Build architecture-dependent files here.
-binary-arch: build install
- dh_testdir
- dh_testroot
- dh_installchangelogs ChangeLog
- dh_installdocs
- dh_installexamples
- dh_install
-# dh_installmenu
-# dh_installdebconf
-# dh_installlogrotate
-# dh_installemacsen
-# dh_installpam
-# dh_installmime
-# dh_installinit
-# dh_installcron
-# dh_installinfo
- dh_installman
- dh_link
- dh_strip
- dh_compress
- dh_fixperms
-# dh_perl
-# dh_python
- dh_makeshlibs
- dh_installdeb
- dh_shlibdeps
- dh_gencontrol
- dh_md5sums
- dh_builddeb
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/genIncludes.sh b/genIncludes.sh
deleted file mode 100755
index 56710e9..0000000
--- a/genIncludes.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#! /bin/bash
-
-createGeneric() {
- echo "-- Creating generic include file: $1.all"
- #Make sure we run into subdirectories first:
- dirs=()
- for file in "$1"/*
- do
- if [ -d "$file" ]
- then
- # Recursion:
- dirs+=( "$file" )
- fi
- done
- for dir in ${dirs[@]}
- do
- createGeneric $dir
- done
- #Now list all files, including newly created .all files:
- if [ -f $1.all ]
- then
- rm $1.all
- fi
- dir=`basename $1`
- for file in "$1"/*
- do
- if [ -f "$file" ] && ( [ "${file##*.}" == "h" ] || [ "${file##*.}" == "all" ] )
- then
- file=`basename $file`
- echo "#include \"$dir/$file\"" >> $1.all
- fi
- done;
-}
-
-createGeneric $1
diff --git a/package.cmake.in b/package.cmake.in
new file mode 100644
index 0000000..f3005c0
--- /dev/null
+++ b/package.cmake.in
@@ -0,0 +1,25 @@
+# CMake package file for Bio++ Core
+# Authors:
+# Francois Gindraud (2017)
+# Created: 08/03/2017
+ at PACKAGE_INIT@
+
+if (NOT @PROJECT_NAME at _FOUND)
+ # No deps
+ # Add targets
+ include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME at -targets.cmake")
+ # Append targets to convenient lists
+ set (BPP_LIBS_STATIC "${BPP_LIBS_STATIC}" @PROJECT_NAME at -static)
+ set (BPP_LIBS_SHARED "${BPP_LIBS_SHARED}" @PROJECT_NAME at -shared)
+ # Print some path info for targets
+ get_property (static-location TARGET @PROJECT_NAME at -static PROPERTY LOCATION)
+ get_property (shared-location TARGET @PROJECT_NAME at -shared PROPERTY LOCATION)
+ get_property (header-location TARGET @PROJECT_NAME at -static PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
+ message (STATUS "@PROJECT_NAME@ @PROJECT_VERSION@ found:")
+ message (STATUS " static lib: ${static-location}")
+ message (STATUS " shared lib: ${shared-location}")
+ message (STATUS " includes: ${header-location}")
+ unset (static-location)
+ unset (shared-location)
+ unset (header-location)
+endif (NOT @PROJECT_NAME at _FOUND)
diff --git a/src/Bpp/App/ApplicationTools.cpp b/src/Bpp/App/ApplicationTools.cpp
index 3480e15..2e6bffa 100644
--- a/src/Bpp/App/ApplicationTools.cpp
+++ b/src/Bpp/App/ApplicationTools.cpp
@@ -58,25 +58,6 @@ float ApplicationTools::terminalSplit = 0.5;
bool ApplicationTools::interactive = true;
int ApplicationTools::warningLevel = 0;
-/******************************************************************************/
-
-bool ApplicationTools::parameterExists(
- const std::string & parameterName,
- std::map<std::string, std::string>& params)
-{
- return (params.find(parameterName) != params.end() && !TextTools::isEmpty(params[parameterName]));
-}
-
-bool ApplicationTools::parameterExists(
- const std::string & parameterName,
- std::vector<std::string>& params)
-{
- for (size_t i = 0; i < params.size(); ++i)
- if (params[i] == parameterName)
- return true;
-
- return false;
-}
/******************************************************************************/
@@ -224,26 +205,6 @@ int ApplicationTools::getIntParameter(
/******************************************************************************/
-std::string ApplicationTools::getStringParameter(
- const std::string& parameterName,
- std::map<std::string, std::string>& params,
- const std::string& defaultValue,
- const std::string& suffix,
- bool suffixIsOptional,
- int warn)
-{
- string sParam = defaultValue;
- if (parameterExists(parameterName + suffix, params)) {
- sParam = params[parameterName + suffix];
- } else if (suffixIsOptional && parameterExists(parameterName, params)) {
- sParam = params[parameterName];
- } else if (warn <= warningLevel) {
- displayWarning("Parameter " + parameterName + " not specified. Default used instead: " + defaultValue);
- }
- return sParam;
-}
-
-/******************************************************************************/
bool ApplicationTools::getBooleanParameter(
const std::string& parameterName,
diff --git a/src/Bpp/App/ApplicationTools.h b/src/Bpp/App/ApplicationTools.h
index a9b40af..77a8ab1 100644
--- a/src/Bpp/App/ApplicationTools.h
+++ b/src/Bpp/App/ApplicationTools.h
@@ -144,9 +144,22 @@ namespace bpp
* @param params The parameter list.
* @return True is the parameter of specified name is in the list.
*/
- static bool parameterExists(const std::string& parameterName, std::map<std::string, std::string>& params);
+ static bool parameterExists(const std::string& parameterName, const std::map<std::string, std::string>& params)
+ {
+ std::map<std::string, std::string>::const_iterator it=params.find(parameterName);
+
+ return (it != params.end() && !TextTools::isEmpty(it->second));
+ }
+
+
+ static bool parameterExists(const std::string& parameterName, std::vector<std::string>& params)
+ {
+ for (size_t i = 0; i < params.size(); ++i)
+ if (params[i] == parameterName)
+ return true;
- static bool parameterExists(const std::string& parameterName, std::vector<std::string>& params);
+ return false;
+ }
/**
* @brief Returns a vector of parameter names that match a given pattern.
@@ -210,13 +223,33 @@ namespace bpp
* @param warn Tell if a warning must be sent in case the parameter is not found.
* @return The corresponding value.
*/
+
static std::string getStringParameter(
const std::string& parameterName,
- std::map<std::string, std::string>& params,
+ const std::map<std::string, std::string>& params,
const std::string& defaultValue,
const std::string& suffix = "",
bool suffixIsOptional = true,
- int warn = 0);
+ int warn = 0)
+ {
+ std::string sParam = defaultValue;
+ std::map<std::string, std::string>::const_iterator it1=params.find(parameterName + suffix);
+ if (it1 != params.end() && !TextTools::isEmpty(it1->second))
+ sParam = it1->second;
+ else
+ {
+ std::map<std::string, std::string>::const_iterator it2=params.find(parameterName);
+ if (suffixIsOptional && it2 != params.end() && !TextTools::isEmpty(it2->second))
+ sParam = it2->second;
+ else
+ if (warn <= warningLevel) {
+ displayWarning("Parameter " + parameterName + " not specified. Default used instead: " + defaultValue);
+ }
+ }
+
+ return sParam;
+ }
+
/**
* @brief Get a boolean parameter.
diff --git a/src/Bpp/App/NumCalcApplicationTools.cpp b/src/Bpp/App/NumCalcApplicationTools.cpp
index 7c2dcf9..71d7cc8 100644
--- a/src/Bpp/App/NumCalcApplicationTools.cpp
+++ b/src/Bpp/App/NumCalcApplicationTools.cpp
@@ -52,6 +52,7 @@ vector<int> NumCalcApplicationTools::seqFromString(const std::string& s, const s
while (st->hasMoreToken())
{
StringTokenizer * st2 = new StringTokenizer(st->nextToken(), seqdelim, true);
+
if (st2->numberOfRemainingTokens() > 1)
{
vector<int> tmp = VectorTools::seq(TextTools::toInt(st2->getToken(0)), TextTools::toInt(st2->getToken(1)), 1);
diff --git a/src/Bpp/BppBoolean.h b/src/Bpp/BppBoolean.h
index 25041ea..78f1f5b 100644
--- a/src/Bpp/BppBoolean.h
+++ b/src/Bpp/BppBoolean.h
@@ -72,12 +72,7 @@ class BppBoolean: public virtual Clonable
*
* @{
*/
-#ifdef NO_VIRTUAL_COV
- Clonable*
-#else
- BppBoolean*
-#endif
- clone() const { return new BppBoolean(*this); }
+ BppBoolean * clone() const { return new BppBoolean(*this); }
/** @} */
const bool getValue() const { return value_; }
diff --git a/src/Bpp/BppString.h b/src/Bpp/BppString.h
index ef6c176..98e942c 100644
--- a/src/Bpp/BppString.h
+++ b/src/Bpp/BppString.h
@@ -75,12 +75,7 @@ class BppString: public virtual Clonable
*
* @{
*/
-#ifdef NO_VIRTUAL_COV
- Clonable*
-#else
- BppString*
-#endif
- clone() const { return new BppString(*this); }
+ BppString * clone() const { return new BppString(*this); }
/** @} */
const std::string& toSTL() const { return text_; }
diff --git a/src/Bpp/BppVector.h b/src/Bpp/BppVector.h
index 8981a43..e9a921c 100644
--- a/src/Bpp/BppVector.h
+++ b/src/Bpp/BppVector.h
@@ -79,12 +79,7 @@ class BppVector: public Clonable
*
* @{
*/
-#ifdef NO_VIRTUAL_COV
- Clonable*
-#else
- BppVector<TYPE>*
-#endif
- clone() const { return new BppVector<TYPE>(*this); }
+ BppVector<TYPE> * clone() const { return new BppVector<TYPE>(*this); }
/** @} */
const std::vector<TYPE>& toSTL() const { return vector_; }
diff --git a/src/Bpp/Clonable.h b/src/Bpp/Clonable.h
index 4b803f7..f976847 100644
--- a/src/Bpp/Clonable.h
+++ b/src/Bpp/Clonable.h
@@ -5,7 +5,7 @@
//
/*
-Copyright or © or Copr. CNRS, (November 17, 2004)
+Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
This software is a computer program whose purpose is to provide utilitary
classes. This file belongs to the Bio++ Project.
@@ -98,23 +98,23 @@ namespace bpp
*/
class Clonable
{
- public:
-
- Clonable() {}
-
- virtual ~Clonable() {}
-
- public:
-
- /**
- * @brief Create a copy of this object and send a pointer to it.
- *
- * @return A pointer toward the copy object.
- */
- virtual Clonable * clone() const = 0;
+ public:
+
+ Clonable() {}
+
+ virtual ~Clonable() {}
+
+ public:
+
+ /**
+ * @brief Create a copy of this object and send a pointer to it.
+ *
+ * @return A pointer toward the copy object.
+ */
+ virtual Clonable * clone() const = 0;
};
} //end of namespace bpp.
-#endif //_CLONABLE_H_
+#endif //_CLONABLE_H_
diff --git a/src/Bpp/Exceptions.cpp b/src/Bpp/Exceptions.cpp
index 7b00a5d..60baf8d 100644
--- a/src/Bpp/Exceptions.cpp
+++ b/src/Bpp/Exceptions.cpp
@@ -76,12 +76,6 @@ NumberFormatException::NumberFormatException(const std::string& text, const std:
badNumber_(badNumber) {}
/******************************************************************************/
-
-IndexOutOfBoundsException::IndexOutOfBoundsException(const std::string& text, size_t badInt, size_t lowerBound, size_t upperBound):
- Exception("out of [" + TextTools::toString(lowerBound) + ", " + TextTools::toString(upperBound) + "])" + text),
- badIndex_(badInt),
- lowerBound_(lowerBound),
- upperBound_(upperBound) {}
vector<size_t> IndexOutOfBoundsException::getBounds() const
{
diff --git a/src/Bpp/Exceptions.h b/src/Bpp/Exceptions.h
index ce62920..2c1bc08 100644
--- a/src/Bpp/Exceptions.h
+++ b/src/Bpp/Exceptions.h
@@ -45,6 +45,7 @@ knowledge of the CeCILL license and that you accept its terms.
#include <stdexcept>
#include <vector>
#include <string>
+#include "Text/TextTools.h"
namespace bpp
{
@@ -311,7 +312,11 @@ class IndexOutOfBoundsException:
* @param lowerBound Lower limit.
* @param upperBound Upper limit.
*/
- IndexOutOfBoundsException(const std::string& text, size_t badInt, size_t lowerBound, size_t upperBound);
+ IndexOutOfBoundsException(const std::string& text, size_t badInt, size_t lowerBound, size_t upperBound) :
+ Exception("out of [" + TextTools::toString(lowerBound) + ", " + TextTools::toString(upperBound) + "])" + text),
+ badIndex_(badInt),
+ lowerBound_(lowerBound),
+ upperBound_(upperBound) {}
virtual ~IndexOutOfBoundsException() throw() {}
diff --git a/src/Bpp/Graph/AssociationDAGraphImplObserver.h b/src/Bpp/Graph/AssociationDAGraphImplObserver.h
new file mode 100644
index 0000000..d5d18c2
--- /dev/null
+++ b/src/Bpp/Graph/AssociationDAGraphImplObserver.h
@@ -0,0 +1,406 @@
+//
+// File AssociationDAGraphImplObserver.h
+// Created by: Laurent Guéguen
+// Last modification : lundi 19 décembre 2016, à 22h 14
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _ASSOCIATION_DAGRAPH_IMPL_OBSERVER_HPP_
+#define _ASSOCIATION_DAGRAPH_IMPL_OBSERVER_HPP_
+
+#include "DAGraphImpl.h"
+#include "AssociationDAGraphObserver.h"
+#include "AssociationGraphImplObserver.h"
+
+#include <vector>
+#include <map>
+#include <iostream>
+#include <ostream>
+#include <memory>
+
+namespace bpp
+{
+template<class N, class E, class DAGraphImpl>
+class AssociationDAGraphImplObserver :
+ public AssociationDAGraphObserver<N, E>,
+ public AssociationGraphImplObserver<N, E, DAGraphImpl>
+{
+public:
+ typedef typename AssociationGraphObserver<N, E>::NodeIndex NodeIndex;
+ typedef typename AssociationGraphObserver<N, E>::EdgeIndex EdgeIndex;
+
+ typedef typename Graph::NodeId NodeGraphid;
+ typedef typename Graph::EdgeId EdgeGraphid;
+
+public:
+ /**
+ * Constructor
+ */
+
+ AssociationDAGraphImplObserver() :
+ AssociationGraphImplObserver<N, E, DAGraphImpl>(true)
+ {}
+
+ /**
+ * Constructor
+ * @param subjectDAGraph the DAGraph which is observed
+ */
+
+ AssociationDAGraphImplObserver(std::shared_ptr<DAGraphImpl> subjectDAGraph) :
+ AssociationGraphImplObserver<N, E, DAGraphImpl>(subjectDAGraph)
+ {}
+
+ /**
+ * Copy Constructor
+ * @param dAGraphObserver the DAGraphObserver to be copied
+ */
+
+ AssociationDAGraphImplObserver(bpp::AssociationDAGraphImplObserver<N, E, DAGraphImpl> const& dAGraphObserver) :
+ AssociationGraphImplObserver<N, E, DAGraphImpl>(dAGraphObserver)
+ {}
+
+
+ /**
+ * Copy Constructor
+ * @param dAGraphObserver the DAGraphObserver to be copied
+ */
+
+ template<class N2, class E2>
+ AssociationDAGraphImplObserver(bpp::AssociationDAGraphImplObserver<N2, E2, DAGraphImpl> const& dAGraphObserver) :
+ AssociationGraphImplObserver<N, E, DAGraphImpl>(dAGraphObserver)
+ {}
+
+ /**
+ * = Operator
+ * @param dAGraphObserver the DAGraphObserver we want to copy the values
+ */
+
+ AssociationDAGraphImplObserver<N, E, DAGraphImpl>& operator=(bpp::AssociationDAGraphImplObserver<N, E, DAGraphImpl> const& dAGraphObserver)
+ {
+ AssociationGraphImplObserver<N, E, DAGraphImpl>::operator=(dAGraphObserver);
+ return *this;
+ }
+
+ /**
+ * Destructor
+ */
+
+ ~AssociationDAGraphImplObserver()
+ {}
+
+ /**
+ * clone function
+ */
+
+ AssociationDAGraphImplObserver<N, E, DAGraphImpl>* clone() const
+ {
+ return new AssociationDAGraphImplObserver<N, E, DAGraphImpl>(*this);
+ }
+
+
+ /**
+ * Is the graph a DAG? A DAG must be acyclic and with no isolated node.
+ * @return true if valid DAG
+ */
+ bool isValid() const
+ {
+ return this->getGraph()->isValid();
+ }
+
+ /**
+ * Is the DAG rooted? Ie with a unique node with no father.
+ * @return true if rooted
+ */
+ bool isRooted() const
+ {
+ return this->getGraph()->isRooted();
+ }
+
+
+ /**
+ * Return the fathers of a node
+ * @param node the concerned node
+ * @return a vector of son Nodes
+ */
+
+ std::vector<std::shared_ptr<N> > getFathers(const std::shared_ptr<N> node) const
+ {
+ return this->getNodesFromGraphid(this->getGraph()->getFathers(this->getNodeGraphid(node)));
+ }
+
+ std::vector<NodeIndex> getFathers(const NodeIndex node) const
+ {
+ return this->getNodeIndexes(this->getNodesFromGraphid(this->getGraph()->getFathers(this->getNodeGraphid(this->getNode(node)))));
+ }
+
+ /**
+ * @brief Sets the root and make the DAG directed from root to
+ * leaves
+ *
+ */
+ void rootAt(const std::shared_ptr<N> root)
+ {
+ this->getGraph()->rootAt(this->getNodeGraphid(root));
+ }
+
+ /**
+ * Has the node a father?
+ */
+ bool hasFather(const std::shared_ptr<N> nodeObject) const
+ {
+ return this->getGraph()->hasFather(this->getNodeGraphid(nodeObject));
+ }
+
+ bool hasFather(const NodeIndex node) const
+ {
+ return this->getGraph()->hasFather(this->getNodeGraphid(this->getNode(node)));
+ }
+
+ /**
+ * Return the sons of a node
+ * @return a vector of son Nodes
+ */
+
+ std::vector<std::shared_ptr<N> > getSons(const std::shared_ptr<N> node) const
+ {
+ return this->getNodesFromGraphid(this->getGraph()->getSons(this->getNodeGraphid(node)));
+ }
+
+ std::vector<NodeIndex> getSons(const NodeIndex node) const
+ {
+ return this->getNodeIndexes(this->getNodesFromGraphid(this->getGraph()->getSons(this->getNodeGraphid(this->getNode(node)))));
+ }
+
+
+ /**
+ * Return the son of an edge
+ * @param edge the concerned edge
+ * @return the son Node
+ */
+
+ std::shared_ptr<N> getSon(const std::shared_ptr<E> edge) const
+ {
+ return this->getNodeFromGraphid(this->getGraph()->getBottom(this->getEdgeGraphid(edge)));
+ }
+
+ NodeIndex getSon(const EdgeIndex edgeId) const
+ {
+ return this->getNodeIndex(this->getNode(this->getGraph()->getBottom(this->getEdgeGraphid(this->getEdge(edgeId)))));
+ }
+
+
+ /**
+ * Return the father of an edge
+ * @param edge the concerned edge
+ * @return the father Node
+ */
+
+ std::shared_ptr<N> getFather(const std::shared_ptr<E> edge) const
+ {
+ return this->getNodeFromGraphid(this->getGraph()->getTop(this->getEdgeGraphid(edge)));
+ }
+
+ NodeIndex getFather(const EdgeIndex edge) const
+ {
+ return this->getNodeIndex(this->getNode(this->getGraph()->getTop(this->getEdgeGraphid(this->getEdge(edge)))));
+ }
+
+ /**
+ * Return the number of fathers
+ * @param node the concerned node
+ * @return the number of fathers
+ */
+ size_t getNumberOfFathers(const std::shared_ptr<N> node) const
+ {
+ return this->getGraph()->getNumberOfFathers(this->getNodeGraphid(node));
+ }
+
+ /**
+ * Return the number of sons
+ * @param node the concerned node
+ * @return the number of sons
+ */
+ size_t getNumberOfSons(const std::shared_ptr<N> node) const
+ {
+ return this->getGraph()->getNumberOfSons(this->getNodeGraphid(node));
+ }
+
+ /**
+ * Get the leaves of a DAG under a peculiar node.
+ *
+ * @param node the starting node
+ * @return a vector containing the leaves
+ */
+
+ std::vector<std::shared_ptr<N> > getLeavesUnderNode(std::shared_ptr<N> node) const
+ {
+ return this->getNodesFromGraphid(this->getGraph()->getLeavesUnderNode(this->getNodeGraphid(node)));
+ }
+
+ /**
+ * Remove the fathers of a node
+ * @return a vector containing the removed fathers
+ */
+
+ std::vector<std::shared_ptr<N> > removeFathers(const std::shared_ptr<N> node)
+ {
+ return this->getNodesFromGraphid(this->getGraph()->removeFathers(this->getNodeGraphid(node)));
+ }
+
+ /**
+ * Remove a father of a node
+ * @return a vector containing the removed nodes
+ */
+ void removeFather(const std::shared_ptr<N> node, const std::shared_ptr<N> father)
+ {
+ this->getGraph()->removeFather(this->getNodeGraphid(node), this->getNodeGraphid(father));
+ }
+
+ /**
+ * Remove the sons of a node
+ * @return a vector containing the removed nodes
+ */
+
+ std::vector<std::shared_ptr<N> > removeSons(const std::shared_ptr<N> node)
+ {
+ return this->getNodesFromGraphid(this->getGraph()->removeSons(this->getNodeGraphid(node)));
+ }
+
+ /**
+ * Remove a son of a node
+ */
+ void removeSon(const std::shared_ptr<N> node, const std::shared_ptr<N> son)
+ {
+ this->getGraph()->removeSon(this->getNodeGraphid(node), this->getNodeGraphid(son));
+ }
+
+ /**
+ * Add a father to a node
+ * @param nodeObject the concerned node
+ * @param fatherNodeObject the node to be added as a father to the node
+ * @param edgeObject the optional edge between the nodes (default
+ * = 00)
+ */
+ void addFather(const std::shared_ptr<N> nodeObject, const std::shared_ptr<N> fatherNodeObject, const std::shared_ptr<E> edgeObject = 0)
+ {
+ if (edgeObject)
+ try
+ {
+ this->getGraph()->addFather(this->getNodeGraphid(nodeObject), this->getNodeGraphid(fatherNodeObject), this->getEdgeGraphid(edgeObject));
+ }
+ catch (Exception& e)
+ {
+ this->link(fatherNodeObject, nodeObject, edgeObject);
+ }
+ else
+ this->getGraph()->addFather(this->getNodeGraphid(nodeObject), this->getNodeGraphid(fatherNodeObject));
+ }
+
+ /**
+ * Add a son to a node
+ * @param nodeObject the concerned node
+ * @param sonNodeObject the node to be added as a son to the father
+ * @param edgeObject the optional edge between the nodes (default
+ * = 00)
+ */
+ void addSon(const std::shared_ptr<N> nodeObject, const std::shared_ptr<N> sonNodeObject, const std::shared_ptr<E> edgeObject = 0)
+ {
+ if (edgeObject)
+ try
+ {
+ this->getGraph()->addSon(this->getNodeGraphid(nodeObject), this->getNodeGraphid(sonNodeObject), this->getEdgeGraphid(edgeObject));
+ }
+ catch (Exception& e)
+ {
+ this->link(nodeObject, sonNodeObject, edgeObject);
+ }
+ else
+ this->getGraph()->addSon(this->getNodeGraphid(nodeObject), this->getNodeGraphid(sonNodeObject));
+ }
+
+ /**
+ * Iterators
+ *
+ */
+
+ /*
+ * @brief builds iterator on the fathers of a Node
+ *
+ */
+
+ std::unique_ptr<typename AssociationDAGraphObserver<N, E>::NodeIterator> fathersIterator(std::shared_ptr<N> node)
+ {
+ return this->incomingNeighborNodesIterator(node);
+ }
+
+ /*
+ * @brief builds iterator on the sons of a Node
+ *
+ */
+
+ std::unique_ptr<typename AssociationDAGraphObserver<N, E>::NodeIterator> sonsIterator(std::shared_ptr<N> node)
+ {
+ return this->outgoingNeighborNodesIterator(node);
+ }
+
+ /**
+ * @brief Get Below Objects.
+ *
+ * @param localRoot of the subgraph.
+ * @return A vector of ancestor nodes ids.
+ *
+ */
+
+ std::vector<std::shared_ptr<N> > getBelowNodes(const std::shared_ptr<N> localRoot)
+ {
+ return this->getNodesFromGraphid(this->getGraph()->getBelowNodes(this->getNodeGraphid(localRoot)));
+ }
+
+ std::vector<std::shared_ptr<E> > getBelowEdges(const std::shared_ptr<N> localRoot)
+ {
+ return AssociationGraphImplObserver<N, E, DAGraphImpl>::getEdgesFromGraphid(this->getGraph()->getBelowEdges(this->getNodeGraphid(localRoot)));
+ }
+};
+
+/********************/
+
+template<class N, class E>
+using AssociationDAGlobalGraphObserver = AssociationDAGraphImplObserver<N, E, DAGlobalGraph>;
+
+/********************/
+}
+
+
+#endif
diff --git a/src/Bpp/Graph/AssociationDAGraphObserver.h b/src/Bpp/Graph/AssociationDAGraphObserver.h
new file mode 100644
index 0000000..e1694e4
--- /dev/null
+++ b/src/Bpp/Graph/AssociationDAGraphObserver.h
@@ -0,0 +1,256 @@
+//
+// File AssociationDAGraphObserver.h
+// Created by: Laurent Guéguen
+// Last modification : lundi 19 décembre 2016, à 21h 48
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _ASSOCIATION_DA_GRAPHOBSERVER_HPP_
+#define _ASSOCIATION_DA_GRAPHOBSERVER_HPP_
+
+#include "DAGraph.h"
+#include "AssociationGraphObserver.h"
+
+#include <vector>
+#include <map>
+#include <iostream>
+#include <ostream>
+#include <memory>
+
+namespace bpp
+{
+/**
+ * @brief Defines a DA Graph Associator. It is a template which
+ * follows (subscribed to) a Graph.
+ *
+ * @author Laurent Guéguen
+ */
+
+template<class N, class E>
+class AssociationDAGraphObserver :
+ public virtual AssociationGraphObserver<N, E>
+{
+public:
+ typedef typename AssociationDAGraphObserver<N, E>::NodeIndex NodeIndex;
+ typedef typename AssociationDAGraphObserver<N, E>::EdgeIndex EdgeIndex;
+
+ typedef typename DAGraph::NodeId NodeGraphid;
+ typedef typename DAGraph::EdgeId EdgeGraphid;
+
+public:
+ /**
+ * Is the graph a DAG? A DAG must be acyclic.
+ * @return true if valid DAG
+ */
+
+ virtual bool isValid() const = 0;
+
+ /**
+ * Is the DAG rooted? Ie with at most one node with no father.
+ * @return true if rooted DAG
+ */
+
+ virtual bool isRooted() const = 0;
+
+ /**
+ * @brief Sets the root and make the DAG directed from root to
+ * leaves
+ *
+ */
+
+ virtual void rootAt(const std::shared_ptr<N> root) = 0;
+
+
+ /**
+ * Return, the fathers of a node
+ * @param node the concerned node
+ * @return the father
+ */
+
+ virtual std::vector<std::shared_ptr<N> > getFathers(const std::shared_ptr<N> node) const = 0;
+
+ virtual std::vector<NodeIndex> getFathers(const NodeIndex node) const = 0;
+
+ /**
+ * Has the node a father?
+ */
+
+ virtual bool hasFather(const std::shared_ptr<N> nodeObject) const = 0;
+ virtual bool hasFather(const NodeIndex node) const = 0;
+
+ /**
+ * Return the sons of a node
+ * @param node the concerned node
+ * @return a vector of son Nodes
+ */
+
+ virtual std::vector<std::shared_ptr<N> > getSons(const std::shared_ptr<N> node) const = 0;
+
+ virtual std::vector<NodeIndex> getSons(const NodeIndex node) const = 0;
+
+ /**
+ * Return the son of an edge
+ * @param edge the concerned edge
+ * @return the son Node
+ */
+
+ virtual std::shared_ptr<N> getSon(const std::shared_ptr<E> edge) const = 0;
+ virtual NodeIndex getSon(const EdgeIndex edge) const = 0;
+
+ /**
+ * Return the father of an edge
+ * @param edge the concerned edge
+ * @return the father Node
+ */
+
+ virtual std::shared_ptr<N> getFather(const std::shared_ptr<E> edge) const = 0;
+ virtual NodeIndex getFather(const EdgeIndex edge) const = 0;
+
+ /**
+ * Return the number of sons
+ * @param node the concerned node
+ * @return the number of sons
+ */
+
+ virtual size_t getNumberOfSons(const std::shared_ptr<N> node) const = 0;
+
+ /**
+ * Return the number of fathers
+ * @param node the concerned node
+ * @return the number of fathers
+ */
+
+ virtual size_t getNumberOfFathers(const std::shared_ptr<N> node) const = 0;
+
+ /**
+ * Get the leaves of a tree under a peculiar node.
+ *
+ * @param node the starting node
+ * @return a vector containing the leaves
+ */
+
+ virtual std::vector<std::shared_ptr<N> > getLeavesUnderNode(std::shared_ptr<N> node) const = 0;
+
+ /**
+ * Remove the sons of a node
+ * @return a vector containing the removed nodes
+ */
+
+ virtual std::vector<std::shared_ptr<N> > removeSons(const std::shared_ptr<N> node) = 0;
+
+ /**
+ * Remove a son of a node
+ * @param node the concerned node
+ * @param son the node to be removed
+ */
+
+ virtual void removeSon(const std::shared_ptr<N> node, const std::shared_ptr<N> son) = 0;
+
+ /**
+ * Add a son to a node
+ * @param nodeObject the concerned node
+ * @param sonNodeObject the node to be added as a son to the father
+ * @param edgeObject the optional edge between the nodes (default
+ * = 0)
+ */
+
+ virtual void addSon(const std::shared_ptr<N> nodeObject, const std::shared_ptr<N> sonNodeObject, const std::shared_ptr<E> edgeObject = 0) = 0;
+
+ /**
+ * Remove the fathers of a node
+ * @return a vector containing the removed fathers
+ */
+
+ virtual std::vector<std::shared_ptr<N> > removeFathers(const std::shared_ptr<N> node) = 0;
+
+ /**
+ * Remove a father of a node
+ */
+
+ virtual void removeFather(const std::shared_ptr<N> node, const std::shared_ptr<N> father) = 0;
+
+ /**
+ * Add a father to a node
+ * @param nodeObject the concerned node
+ * @param fatherNodeObject the node to be added as a father to the node
+ * @param edgeObject the optional edge between the nodes (default
+ * = 00)
+ */
+
+ virtual void addFather(const std::shared_ptr<N> nodeObject, const std::shared_ptr<N> fatherNodeObject, const std::shared_ptr<E> edgeObject = 0) = 0;
+
+ /**
+ * Iterators
+ *
+ */
+
+ /*
+ * @brief builds iterator on the neighbor nodes of a Node
+ *
+ */
+
+ typedef typename AssociationGraphObserver<N, E>::NodeIterator NodeIterator;
+ typedef typename AssociationGraphObserver<N, E>::EdgeIterator EdgeIterator;
+
+
+ /*
+ * @brief builds iterator on the sons of a Node
+ *
+ */
+
+ virtual std::unique_ptr<NodeIterator> sonsIterator(std::shared_ptr<N> node) = 0;
+
+ /*
+ * @brief builds iterator on the fathers of a Node
+ *
+ */
+
+ virtual std::unique_ptr<NodeIterator> fathersIterator(std::shared_ptr<N> node) = 0;
+
+ /**
+ * @brief Get Below Objects.
+ *
+ * @param localRoot of the subgraph.
+ * @return A vector of ancestor nodes ids.
+ *
+ */
+
+ virtual std::vector<std::shared_ptr<N> > getBelowNodes(const std::shared_ptr<N> localRoot) = 0;
+
+ virtual std::vector<std::shared_ptr<E> > getBelowEdges(const std::shared_ptr<N> localRoot) = 0;
+};
+}
+
+#endif
diff --git a/src/Bpp/Graph/AssociationGraphImplObserver.h b/src/Bpp/Graph/AssociationGraphImplObserver.h
new file mode 100644
index 0000000..3a4409e
--- /dev/null
+++ b/src/Bpp/Graph/AssociationGraphImplObserver.h
@@ -0,0 +1,1332 @@
+//
+// File AssociationGraphImplObserver.h
+// Created by: Thomas Bigot
+// Last modification : vendredi 4 novembre 2016, à 10h 21
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _ASSOCIATION_GRAPH_IMPL_OBSERVER_HPP_
+#define _ASSOCIATION_GRAPH_IMPL_OBSERVER_HPP_
+
+#include "AssociationGraphObserver.h"
+#include "GlobalGraph.h"
+
+#include "../Exceptions.h"
+#include "../Clonable.h"
+
+#include <vector>
+#include <map>
+#include <iostream>
+#include <ostream>
+#include <memory>
+#include <type_traits>
+
+namespace bpp
+{
+template<class N, class E, class GraphImpl>
+class AssociationGraphImplObserver : public virtual AssociationGraphObserver<N, E>
+{
+public:
+ typedef typename AssociationGraphObserver<N, E>::NodeIndex NodeIndex;
+ typedef typename AssociationGraphObserver<N, E>::EdgeIndex EdgeIndex;
+
+ typedef Graph::NodeId NodeGraphid;
+ typedef Graph::EdgeId EdgeGraphid;
+
+protected:
+ /**
+ * The observed Graph. Anytime this graph is observed,
+ * the current object will be warned to take changes into account.
+ */
+
+ std::shared_ptr<GraphImpl> subjectGraph_;
+
+private:
+ /**
+ * Registration with Graph Ids.
+ *
+ * @{
+ */
+
+ /**
+ * List of nodes, stored at the same ID than the corresponding nodes
+ * in the observed graph.
+ */
+ std::vector<std::shared_ptr<N> > graphidToN_;
+
+ /**
+ * List of edges, stored at the same ID than the corresponding edges
+ * in the observed graph.
+ */
+ std::vector<std::shared_ptr<E> > graphidToE_;
+
+ /**
+ * Can find a Node with the corresponding object.
+ */
+ std::map<std::shared_ptr<N>, NodeGraphid> NToGraphid_;
+
+ /**
+ * Can find an Edge with the corresponding object.
+ */
+ std::map<std::shared_ptr<E>, EdgeGraphid> EToGraphid_;
+
+ /*
+ * @}
+ */
+
+ /**
+ * Registration with own Ids.
+ *
+ * @{
+ */
+
+ /**
+ * List of nodes, stored at a given index.
+ */
+ std::vector<std::shared_ptr<N> > indexToN_;
+
+ /**
+ * List of edges, stored at a given index.
+ */
+ std::vector<std::shared_ptr<E> > indexToE_;
+
+ /**
+ * Can find a Node index with the corresponding object.
+ */
+ std::map<std::shared_ptr<N>, NodeIndex> NToIndex_;
+
+ /**
+ * Can find an Edge index with the corresponding object.
+ */
+ std::map<std::shared_ptr<E>, EdgeIndex> EToIndex_;
+
+ /*
+ * @}
+ */
+
+
+ /**
+ * defines a type of neighbors : incoming and/or outgoing
+ */
+ enum neighborType {INCOMING, OUTGOING, BOTH};
+
+ /**
+ * Get incoming / outgoing neighbors according to the enum type
+ */
+
+ std::vector<std::shared_ptr<N> > getNeighbors_(const std::shared_ptr<N> nodeObject, neighborType type) const
+ {
+ NodeGraphid node = getNodeGraphid(nodeObject);
+
+ // PHASE 1: getting the right neighbors
+ std::vector<NodeGraphid> neighbors;
+ switch (type)
+ {
+ case OUTGOING:
+ neighbors = getGraph()->getOutgoingNeighbors(node);
+ break;
+ case INCOMING:
+ neighbors = getGraph()->getIncomingNeighbors(node);
+ break;
+ case BOTH:
+ neighbors = getGraph()->getNeighbors(node);
+ }
+ return getNodesFromGraphid(neighbors);
+ }
+
+ /**
+ * Get incoming / outgoing edges according to the enum type
+ */
+ std::vector<std::shared_ptr<E> > getEdges_(const std::shared_ptr<N> nodeObject, neighborType type) const
+ {
+ NodeGraphid node = getNodeGraphid(nodeObject);
+
+ // PHASE 1: getting the right neighbors
+ std::vector<EdgeGraphid> edges;
+ switch (type)
+ {
+ case OUTGOING:
+ edges = getGraph()->getOutgoingEdges(node);
+ break;
+ case INCOMING:
+ edges = getGraph()->getIncomingEdges(node);
+ break;
+ case BOTH:
+ edges = getGraph()->getEdges(node);
+ }
+ return getEdgesFromGraphid(edges);
+ }
+
+public:
+ /**
+ * Constructor
+ * @param directed is the graph directed
+ */
+
+ AssociationGraphImplObserver(bool directed = false) :
+ subjectGraph_(new GraphImpl(directed)),
+ graphidToN_(),
+ graphidToE_(),
+ NToGraphid_(),
+ EToGraphid_(),
+ indexToN_(),
+ indexToE_(),
+ NToIndex_(),
+ EToIndex_()
+ {
+ getGraph()->registerObserver(this);
+ }
+
+ /**
+ * Constructor
+ * @param subjectGraph the graph which is observed
+ */
+
+ AssociationGraphImplObserver(std::shared_ptr<GraphImpl> subjectGraph = 00) :
+ subjectGraph_(subjectGraph ? subjectGraph : new GraphImpl()),
+ graphidToN_(),
+ graphidToE_(),
+ NToGraphid_(),
+ EToGraphid_(),
+ indexToN_(),
+ indexToE_(),
+ NToIndex_(),
+ EToIndex_()
+ {
+ getGraph()->registerObserver(this);
+ }
+
+ /**
+ * Copy Constructor
+ * @param graphObserver the graphObserver to be copied
+ */
+
+ template<class N2, class E2>
+ AssociationGraphImplObserver(AssociationGraphImplObserver<N2, E2, GraphImpl> const& graphObserver) :
+ subjectGraph_(graphObserver.getGraph()),
+ graphidToN_(graphObserver.graphidToN_.size()),
+ graphidToE_(graphObserver.graphidToE_.size()),
+ NToGraphid_(),
+ EToGraphid_(),
+ indexToN_(graphObserver.indexToN_.size()),
+ indexToE_(graphObserver.indexToE_.size()),
+ NToIndex_(),
+ EToIndex_()
+ {
+ for (typename std::map<std::shared_ptr<N2>, NodeGraphid >::const_iterator itN = graphObserver.NToGraphid_.begin();
+ itN != graphObserver.NToGraphid_.end(); itN++)
+ {
+ std::shared_ptr<N> node(AssociationGraphObserver<N, E>::template copy<N2, N>(*itN->first));
+
+ NToGraphid_[node] = itN->second;
+ graphidToN_[itN->second] = node;
+
+ typename std::map<std::shared_ptr<N2>, typename AssociationGraphObserver<N2, E2>::NodeIndex>::const_iterator indN = graphObserver.NToIndex_.find(itN->first);
+
+ if (indN != graphObserver.NToIndex_.end())
+ {
+ NToIndex_[node] = indN->second;
+ indexToN_[indN->second] = node;
+ }
+ }
+
+ for (typename std::map<std::shared_ptr<E2>, EdgeGraphid >::const_iterator itE = graphObserver.EToGraphid_.begin();
+ itE != graphObserver.EToGraphid_.end(); itE++)
+ {
+ std::shared_ptr<E> edge(AssociationGraphObserver<N, E>::template copy<E2, E>(*itE->first));
+
+ EToGraphid_[edge] = itE->second;
+ graphidToE_[itE->second] = edge;
+
+ typename std::map<std::shared_ptr<E2>, typename AssociationGraphObserver<N2, E2>::EdgeIndex>::const_iterator indE = graphObserver.EToIndex_.find(itE->first);
+
+ if (indE != graphObserver.EToIndex_.end())
+ {
+ EToIndex_[edge] = indE->second;
+ indexToE_[indE->second] = edge;
+ }
+ }
+
+ getGraph()->registerObserver(this);
+ }
+
+ AssociationGraphImplObserver(AssociationGraphImplObserver<N, E, GraphImpl> const& graphObserver) :
+ subjectGraph_(graphObserver.subjectGraph_),
+ graphidToN_(graphObserver.graphidToN_.size()),
+ graphidToE_(graphObserver.graphidToE_.size()),
+ NToGraphid_(),
+ EToGraphid_(),
+ indexToN_(graphObserver.indexToN_.size()),
+ indexToE_(graphObserver.indexToE_.size()),
+ NToIndex_(),
+ EToIndex_()
+ {
+ for (typename std::map<std::shared_ptr<N>, NodeGraphid >::const_iterator itN = graphObserver.NToGraphid_.begin();
+ itN != graphObserver.NToGraphid_.end(); itN++)
+ {
+ std::shared_ptr<N> node(AssociationGraphObserver<N, E>::template copy<N, N>(*itN->first));
+
+ NToGraphid_[node] = itN->second;
+ graphidToN_[itN->second] = node;
+
+ typename std::map<std::shared_ptr<N>, typename AssociationGraphObserver<N, E>::NodeIndex>::const_iterator indN = graphObserver.NToIndex_.find(itN->first);
+
+ if (indN != graphObserver.NToIndex_.end())
+ {
+ NToIndex_[node] = indN->second;
+ indexToN_[indN->second] = node;
+ }
+ }
+
+ for (typename std::map<std::shared_ptr<E>, EdgeGraphid >::const_iterator itE = graphObserver.EToGraphid_.begin();
+ itE != graphObserver.EToGraphid_.end(); itE++)
+ {
+ std::shared_ptr<E> edge(AssociationGraphObserver<N, E>::template copy<E, E>(*itE->first));
+
+ EToGraphid_[edge] = itE->second;
+ graphidToE_[itE->second] = edge;
+
+ typename std::map<std::shared_ptr<E>, typename AssociationGraphObserver<N, E>::EdgeIndex>::const_iterator indE = graphObserver.EToIndex_.find(itE->first);
+
+ if (indE != graphObserver.EToIndex_.end())
+ {
+ EToIndex_[edge] = indE->second;
+ indexToE_[indE->second] = edge;
+ }
+ }
+
+ getGraph()->registerObserver(this);
+ }
+
+
+ /**
+ * = Operator
+ * @param graphObserver the graphObserver we want to copy the values
+ */
+
+ AssociationGraphImplObserver<N, E, GraphImpl>& operator=(bpp::AssociationGraphImplObserver<N, E, GraphImpl> const& graphObserver)
+ {
+ this->graphidToN_.resize(graphObserver.graphidToN_.size());
+ this->graphidToE_.resize(graphObserver.graphidToE_.size());
+ this->indexToN_.resize(graphObserver.indexToN_.size());
+ this->indexToE_.resize(graphObserver.indexToE_.size());
+
+ for (typename std::map<std::shared_ptr<N>, NodeGraphid >::const_iterator itN = graphObserver.NToGraphid_.begin();
+ itN != graphObserver.NToGraphid_.end(); itN++)
+ {
+ std::shared_ptr<N> node(AssociationGraphObserver<N, E>::template copy<N, N>(*itN->first));
+
+ NToGraphid_[node] = itN->second;
+ graphidToN_[itN->second] = node;
+
+ typename std::map<std::shared_ptr<N>, typename AssociationGraphObserver<N, E>::NodeIndex>::const_iterator indN = graphObserver.NToIndex_.find(itN->first);
+
+ if (indN != graphObserver.NToIndex_.end())
+ {
+ NToIndex_[node] = indN->second;
+ indexToN_[indN->second] = node;
+ }
+ }
+
+ for (typename std::map<std::shared_ptr<E>, EdgeGraphid >::const_iterator itE = graphObserver.EToGraphid_.begin(); itE != graphObserver.EToGraphid_.end(); itE++)
+ {
+ std::shared_ptr<E> edge(AssociationGraphObserver<N, E>::template copy<E, E>(*itE->first));
+
+ EToGraphid_[edge] = itE->second;
+ graphidToE_[itE->second] = edge;
+
+ typename std::map<std::shared_ptr<E>, typename AssociationGraphObserver<N, E>::EdgeIndex>::const_iterator indE = graphObserver.EToIndex_.find(itE->first);
+
+ if (indE != graphObserver.EToIndex_.end())
+ {
+ EToIndex_[edge] = indE->second;
+ indexToE_[indE->second] = edge;
+ }
+ }
+
+ this->subjectGraph_ = graphObserver.getGraph();
+
+ this->getGraph()->registerObserver(this);
+
+ return *this;
+ }
+
+
+ /**
+ * Destructor
+ */
+
+ ~AssociationGraphImplObserver()
+ {
+ getGraph()->unregisterObserver(this);
+ }
+
+ /**
+ * clone function
+ */
+
+ AssociationGraphImplObserver<N, E, GraphImpl>* clone() const { return new AssociationGraphImplObserver<N, E, GraphImpl>(*this); }
+
+ const std::shared_ptr<GraphImpl> getGraph() const
+ {
+ return subjectGraph_;
+ }
+
+ std::shared_ptr<GraphImpl> getGraph()
+ {
+ return subjectGraph_;
+ }
+
+ /**
+ * This function is called to tell the observer that the subject
+ * has changed and hence the observer has to take the changes
+ * into account.
+ */
+ void update();
+
+
+ /** @name Graph Relations Management
+ * Modificating the structure of the graph.
+ */
+ // /@{
+
+ /**
+ * Creates an orphaned node from a NodeClass object.
+ * @param nodeObject the N object associated to the node in the graph.
+ *
+ */
+ void createNode(std::shared_ptr<N> nodeObject)
+ {
+ if (NToGraphid_.find(nodeObject) != NToGraphid_.end())
+ throw Exception("AssociationGraphImplObserver::createNode : node already exists");
+
+ unsigned int newGraphNode = getGraph()->createNode();
+ associateNode(nodeObject, newGraphNode);
+ }
+
+ /**
+ * Creates an node linked to an existing node. Order of parameters match
+ * the link method.
+ * @param objectOriginNode existing node. In a directed graph: origin -> newNode.
+ * @param newNodeObject the N object associated to the node in the graph.
+ * @param newEdgeObject the optional edge between the nodes (default
+ * = 00)
+ */
+ void createNode(std::shared_ptr<N> objectOriginNode, std::shared_ptr<N> newNodeObject, std::shared_ptr<E> newEdgeObject = 00)
+ {
+ createNode(newNodeObject);
+ link(objectOriginNode, newNodeObject, newEdgeObject);
+ }
+
+public:
+ /**
+ * Creates a link between two existing nodes.
+ * If directed graph: nodeA -> nodeB.
+ * @param nodeObjectA source node (or first node if undirected)
+ * @param nodeObjectB target node (or second node if undirected)
+ * @param edgeObject the optional edge between the nodes (default
+ * = 00)
+ */
+ void link(std::shared_ptr<N> nodeObjectA, std::shared_ptr<N> nodeObjectB, std::shared_ptr<E> edgeObject = 00)
+ {
+ // checking the nodes
+ typename std::map<std::shared_ptr<N>, NodeGraphid>::iterator foundNodeA, foundNodeB;
+ foundNodeA = NToGraphid_.find(nodeObjectA);
+ foundNodeB = NToGraphid_.find(nodeObjectB);
+ if (foundNodeA == NToGraphid_.end() || foundNodeB == NToGraphid_.end())
+ throw Exception("One of the nodes is not in the graph observer.");
+
+ // checking if the edge is not already in the GraphObserver
+ if (edgeObject != 00 && EToGraphid_.find(edgeObject) != EToGraphid_.end())
+ throw Exception("The given edge is already associated to a relation in the subjectGraph.");
+
+// std::cout << "Trying to link node " << foundNodeA->second << " -> " << foundNodeB->second << std::endl;
+ EdgeGraphid newGraphEdge = getGraph()->link(foundNodeA->second, foundNodeB->second);
+
+ if (graphidToE_.size() < newGraphEdge + 1)
+ graphidToE_.resize(newGraphEdge + 1);
+ graphidToE_.at(newGraphEdge) = edgeObject;
+ EToGraphid_[edgeObject] = newGraphEdge;
+ }
+
+
+ /**
+ * Deletes the link between two existing nodes in the graph.
+ */
+ void unlink(std::shared_ptr<N> nodeObjectA, std::shared_ptr<N> nodeObjectB)
+ {
+ // checking the nodes
+ typename std::map<std::shared_ptr<N>, NodeGraphid>::iterator foundNodeA, foundNodeB;
+ foundNodeA = NToGraphid_.find(nodeObjectA);
+ foundNodeB = NToGraphid_.find(nodeObjectB);
+ if (foundNodeA == NToGraphid_.end() || foundNodeB == NToGraphid_.end())
+ throw Exception("One of the nodes is not in the graph observer.");
+
+ getGraph()->unlink(foundNodeA->second, foundNodeB->second);
+ }
+
+public:
+ /**
+ * Deletes a node
+ * @param nodeObject node to be deleted. The N node object given in argument is not deleted.
+ */
+ void deleteNode(std::shared_ptr<N> nodeObject)
+ {
+ // first deleting the node in the graph
+ getGraph()->deleteNode(getNodeGraphid(nodeObject));
+ // then forgetting
+ dissociateNode(nodeObject);
+ }
+
+
+ // /@}
+
+ /** @name Object Association
+ * Associate or dissociate N and E objects to pre-existing Graph Nodes and Graph Edges
+ */
+ // /@{
+
+ /**
+ * Associate a N object to a node in the graph.
+ * @param nodeObject object to associate
+ * @param graphNode existing node to be associated
+ */
+ void associateNode(std::shared_ptr<N> nodeObject, NodeGraphid graphNode)
+ {
+ // nodes vector must be the right size. Eg: to store a node with
+ // the ID 3, the vector must be of size 4: {0,1,2,3} (size = 4)
+ if (graphidToN_.size() < graphNode + 1)
+ graphidToN_.resize(graphNode + 1);
+
+ // now storing the node
+ graphidToN_.at(graphNode) = nodeObject;
+ NToGraphid_[nodeObject] = graphNode;
+ }
+
+ /**
+ * Associate a E object to an edge in the graph.
+ * @param edgeObject object to associate
+ * @param graphEdge existing edge to be associated
+ */
+ void associateEdge(std::shared_ptr<E> edgeObject, EdgeGraphid graphEdge)
+ {
+ // nodes vector must be the right size. Eg: to store an edge with
+ // the ID 3, the vector must be of size 4: {0,1,2,3} (size = 4)
+ if (graphidToE_.size() < graphEdge + 1)
+ graphidToE_.resize(graphEdge + 1);
+
+ // now storing the edge
+ graphidToE_.at(graphEdge) = edgeObject;
+ EToGraphid_[edgeObject] = graphEdge;
+ }
+
+ /**
+ * Dissociate a N or E object to a node or an edge in the graph.
+ * @param nodeObject object to dissociate
+ */
+ void dissociateNode(std::shared_ptr<N> nodeObject)
+ {
+ typename std::map<std::shared_ptr<N>, NodeGraphid>::iterator nodeToForget = NToGraphid_.find(nodeObject);
+ graphidToN_.at(nodeToForget->second) = 00;
+ NToGraphid_.erase(nodeToForget);
+ }
+
+
+ void dissociateEdge(std::shared_ptr<E> edgeObject)
+ {
+ typename std::map<std::shared_ptr<E>, EdgeGraphid>::iterator edgeToForget = EToGraphid_.find(edgeObject);
+ graphidToE_.at(edgeToForget->second) = 00;
+ EToGraphid_.erase(edgeToForget);
+ }
+
+
+ /**
+ * Return the associated Node ID
+ * @param nodeObject object which to return the node ID
+ * @return a node ID
+ */
+ NodeGraphid getNodeGraphid(const std::shared_ptr<N> nodeObject) const
+ {
+ typename std::map<std::shared_ptr<N>, NodeGraphid>::const_iterator found = NToGraphid_.find(nodeObject);
+ if (found == NToGraphid_.end())
+ throw Exception("Unexisting node object.");
+ return found->second;
+ }
+
+
+ /**
+ * Return the associated Edge ID
+ * @param edgeObject object which to return the node ID
+ * @return a edge ID
+ */
+ EdgeGraphid getEdgeGraphid(const std::shared_ptr<E> edgeObject) const
+ {
+ typename std::map<std::shared_ptr<E>, EdgeGraphid>::const_iterator found = EToGraphid_.find(edgeObject);
+ if (found == EToGraphid_.end())
+ throw Exception("Unexisting edge object.");
+ return found->second;
+ }
+
+
+ /**
+ * Transforms an (a list of) id(s) into an (a list of) object(s)
+ */
+ std::shared_ptr<N> getNodeFromGraphid(NodeGraphid node)
+ {
+ return graphidToN_.at(node);
+ }
+
+ const std::shared_ptr<N> getNodeFromGraphid(NodeGraphid node) const
+ {
+ return graphidToN_.at(node);
+ }
+
+ std::vector<std::shared_ptr<N> > getNodesFromGraphid(std::vector<NodeGraphid> nodes) const
+ {
+ std::vector<std::shared_ptr<N> > nodeObjects;
+ for (typename std::vector<NodeGraphid>::iterator currNode = nodes.begin(); currNode != nodes.end(); currNode++)
+ {
+ if (*currNode > graphidToN_.size())
+ continue;
+ std::shared_ptr<N> foundNodeObject = graphidToN_.at(*currNode);
+ if (!foundNodeObject)
+ continue;
+ nodeObjects.push_back(foundNodeObject);
+ }
+ return nodeObjects;
+ }
+
+ std::shared_ptr<E> getEdgeFromGraphid(EdgeGraphid edge)
+ {
+ return graphidToE_.at(edge);
+ }
+
+ const std::shared_ptr<E> getEdgeFromGraphid(EdgeGraphid edge) const
+ {
+ return graphidToE_.at(edge);
+ }
+
+
+ std::vector<std::shared_ptr<E> > getEdgesFromGraphid(std::vector<EdgeGraphid> edges) const
+ {
+ std::vector<std::shared_ptr<E> > edgeObjects;
+ for (typename std::vector<EdgeGraphid>::iterator currEdge = edges.begin(); currEdge != edges.end(); currEdge++)
+ {
+ if (*currEdge > graphidToE_.size())
+ continue;
+ std::shared_ptr<E> foundEdgeObject = graphidToE_.at(*currEdge);
+ if (!foundEdgeObject)
+ continue;
+ edgeObjects.push_back(foundEdgeObject);
+ }
+ return edgeObjects;
+ }
+
+
+ /**
+ * @brief set the root (but no checking, prefer rootAt)
+ */
+ void setRoot(const std::shared_ptr<N> newRoot)
+ {
+ return getGraph()->setRoot(getNodeGraphid(newRoot));
+ }
+
+ /**
+ * @return the root
+ */
+
+ std::shared_ptr<N> getRoot() const
+ {
+ return this->getNodeFromGraphid(this->getGraph()->getRoot());
+ }
+
+ NodeIndex getRootIndex() const
+ {
+ return this->getNodeIndex(this->getNodeFromGraphid(this->getGraph()->getRoot()));
+ }
+
+ // /@}
+
+ /** @name Object Indexation
+ * Get or set indexes to nodes and edges
+ */
+ // /@{
+
+ /*
+ * @brief Return if object has an index.
+ *
+ */
+ bool hasIndex(const std::shared_ptr<N> nodeObject) const
+ {
+ typename std::map<std::shared_ptr<N>, typename AssociationGraphObserver<N, E>::NodeIndex>::const_iterator found = NToIndex_.find(nodeObject);
+ return found != NToIndex_.end();
+ }
+
+ bool hasIndex(const std::shared_ptr<E> edgeObject) const
+ {
+ typename std::map<std::shared_ptr<E>, typename AssociationGraphObserver<N, E>::EdgeIndex>::const_iterator found = EToIndex_.find(edgeObject);
+ return found != EToIndex_.end();
+ }
+
+ /**
+ * Return the associated Node index
+ * @param nodeObject object which to return the node index
+ * @return a node index
+ */
+ NodeIndex getNodeIndex(const std::shared_ptr<N> nodeObject) const
+ {
+ typename std::map<std::shared_ptr<N>, typename AssociationGraphObserver<N, E>::NodeIndex>::const_iterator found = NToIndex_.find(nodeObject);
+ if (found == NToIndex_.end())
+ throw Exception("Node object with graph id " + TextTools::toString(getNodeGraphid(nodeObject)) + " has no index.");
+
+ return found->second;
+ }
+
+ std::vector<NodeIndex> getNodeIndexes(std::vector<std::shared_ptr<N> > nodes) const
+ {
+ std::vector<NodeIndex> nodeIndexes;
+ for (typename std::vector<std::shared_ptr<N> >::iterator currNode = nodes.begin(); currNode != nodes.end(); currNode++)
+ {
+ nodeIndexes.push_back(getNodeIndex(*currNode));
+ }
+ return nodeIndexes;
+ }
+
+ /**
+ * Return the associated Node index
+ * @param edgeObject object which to return the node index
+ * @return a node index
+ */
+ EdgeIndex getEdgeIndex(const std::shared_ptr<E> edgeObject) const
+ {
+ typename std::map<std::shared_ptr<E>, typename AssociationGraphObserver<N, E>::EdgeIndex>::const_iterator found = EToIndex_.find(edgeObject);
+ if (found == EToIndex_.end())
+ throw Exception("Edge object with graph id " + TextTools::toString(getEdgeGraphid(edgeObject)) + " has no index.");
+ return found->second;
+ }
+
+ std::vector<EdgeIndex> getEdgeIndexes(std::vector<std::shared_ptr<E> > edges) const
+ {
+ std::vector<EdgeIndex> edgeIndexes;
+ for (typename std::vector<std::shared_ptr<E> >::iterator currEdge = edges.begin(); currEdge != edges.end(); currEdge++)
+ {
+ edgeIndexes.push_back(getEdgeIndex(*currEdge));
+ }
+ return edgeIndexes;
+ }
+
+ /**
+ * Set an index associated to a node
+ * @param nodeObject object to which one want to set the index
+ * @param index intex to be given, 0 to get the first free index
+ * @return the given index
+ */
+ NodeIndex setNodeIndex(const std::shared_ptr<N> nodeObject, NodeIndex index)
+ {
+ // TODO: check if this object has already an index?
+
+ // nodes vector must be the right size. Eg: to store a node with
+ // the index 3, the vector must be of size 4: {0,1,2,3} (size = 4)
+ if (index >= indexToN_.size())
+ indexToN_.resize(index + 1);
+
+ // now storing the node
+ indexToN_.at(index) = nodeObject;
+ NToIndex_[nodeObject] = index;
+ return index;
+ }
+
+ /**
+ * Set an index associated to an edge
+ * @param edgeObject object to which one want to set the index
+ * @param index intex to be given, 0 to get the first free index
+ * @return the given index
+ */
+ EdgeIndex setEdgeIndex(const std::shared_ptr<E> edgeObject, EdgeIndex index)
+ {
+ // TODO: check if this object has already an index?
+
+ // nodes vector must be the right size. Eg: to store an edge with
+ // the index 3, the vector must be of size 4: {0,1,2,3} (size = 4)
+ if (index >= indexToE_.size())
+ indexToE_.resize(index + 1);
+
+ // now storing the edge
+ indexToE_.at(index) = edgeObject;
+ EToIndex_[edgeObject] = index;
+ return index;
+ }
+
+ /**
+ * Return the associated Node index
+ * @param node object which to return the node index
+ * @return a node index
+ */
+
+ std::shared_ptr<N> getNode(NodeIndex node) const
+ {
+ return indexToN_.at(node);
+ }
+
+ /**
+ * Return the associated Node index
+ * @param edge object which to return the node index
+ * @return a node index
+ */
+
+ std::shared_ptr<E> getEdge(EdgeIndex edge) const
+ {
+ return indexToE_.at(edge);
+ }
+
+ // /@}
+
+ /** @name Topology exploration
+ * These methodes of the graph concern the topology exploration.
+ */
+ // /@{
+
+ /**
+ * @name Iterators on Nodes
+ *
+ */
+
+ template<class GraphIterator, bool is_const>
+ class NodeIteratorClass :
+ virtual public AssociationGraphObserver<N, E>::NodeIterator
+ {
+private:
+ NodesIteratorClass<GraphIterator, is_const> it_;
+ const AssociationGraphImplObserver<N, E, GraphImpl>& agio_;
+
+public:
+ NodeIteratorClass<GraphIterator, is_const>(AssociationGraphImplObserver<N, E, GraphImpl> &agio) : it_(*agio.getGraph()),
+ agio_(agio) { start(); };
+
+ NodeIteratorClass<GraphIterator, is_const>(const AssociationGraphImplObserver<N, E, GraphImpl> &agio) : it_(*agio.getGraph()),
+ agio_(agio) { start(); };
+
+ NodeIteratorClass<GraphIterator, is_const>(AssociationGraphImplObserver<N, E, GraphImpl> &agio, std::shared_ptr<N> n) : it_(*agio.getGraph(), agio.getNodeGraphid(n)),
+ agio_(agio) {start(); };
+
+ NodeIteratorClass<GraphIterator, is_const>(const AssociationGraphImplObserver<N, E, GraphImpl> &agio, std::shared_ptr<N> n) : it_(*agio.getGraph(), agio.getNodeGraphid(n)),
+ agio_(agio) {start(); };
+
+ ~NodeIteratorClass<GraphIterator, is_const>() {}
+
+ void next() {it_.next(); while (!it_.end() && agio_.getNodeFromGraphid(*it_) == 0) it_.next(); }
+
+ bool end() const {return it_.end(); }
+
+ void start() { it_.start(); while (!it_.end() && (agio_.getNodeFromGraphid(*it_) == 0)) it_.next(); }
+
+ std::shared_ptr<N> operator*() {return agio_.getNodeFromGraphid(*it_); }
+ };
+
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::NodeIterator> allNodesIterator()
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::ALLGRAPHITER, false> >(new AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::ALLGRAPHITER, false>(*this));
+ }
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::NodeIterator> allNodesIterator() const
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::ALLGRAPHITER, true> >(new AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::ALLGRAPHITER, true>(*this));
+ }
+
+
+ /*
+ * @brief builds iterator on the neighbor nodes of a Node
+ *
+ */
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::NodeIterator> outgoingNeighborNodesIterator(std::shared_ptr<N> node)
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::OUTGOINGNEIGHBORITER, false> >(new AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::OUTGOINGNEIGHBORITER, false>(*this, node));
+ }
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::NodeIterator> outgoingNeighborNodesIterator(std::shared_ptr<N> node) const
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::OUTGOINGNEIGHBORITER, true> >(new AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::OUTGOINGNEIGHBORITER, true>(*this, node));
+ }
+
+
+ /*
+ * @brief builds iterator on the neighbor nodes of a Node
+ *
+ */
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::NodeIterator> incomingNeighborNodesIterator(std::shared_ptr<N> node)
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::INCOMINGNEIGHBORITER, false> >(new AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::INCOMINGNEIGHBORITER, false>(*this, node));
+ }
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::NodeIterator> incomingNeighborNodesIterator(std::shared_ptr<N> node) const
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::INCOMINGNEIGHBORITER, true> >(new AssociationGraphImplObserver<N, E, GraphImpl>::NodeIteratorClass<Graph::INCOMINGNEIGHBORITER, true>(*this, node));
+ }
+
+
+ /**
+ * Get all the neighbors of a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the neighbors
+ */
+ std::vector<std::shared_ptr<N> > getNeighbors(const std::shared_ptr<N> node) const
+ {
+ return getNeighbors_(node, BOTH);
+ }
+
+ std::vector<NodeIndex> getNeighbors(NodeIndex node) const
+ {
+ return getNodeIndexes(getNeighbors(getNode(node)));
+ }
+
+ /**
+ * Get all the edges of a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the edges
+ */
+
+ std::vector<std::shared_ptr<E> > getEdges(const std::shared_ptr<N> node) const
+ {
+ return getEdges_(node, BOTH);
+ }
+
+ std::vector<EdgeIndex> getEdges(NodeIndex node) const
+ {
+ return getEdgeIndexes(getEdges(getNode(node)));
+ }
+
+
+ /**
+ * In an directed graph, get all the neighbors which
+ * are leaving a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the outgoing neighbors
+ */
+ std::vector<std::shared_ptr<N> > getOutgoingNeighbors(const std::shared_ptr<N> node) const
+ {
+ return getNeighbors_(node, OUTGOING);
+ }
+
+ std::vector<NodeIndex> getOutgoingNeighbors(NodeIndex node) const
+ {
+ return getNodeIndexes(getOutgoingNeighbors(getNode(node)));
+ }
+
+ /**
+ * In an directed graph, get all the edges which
+ * are leaving a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the outgoing edges
+ */
+ std::vector<std::shared_ptr<E> > getOutgoingEdges(const std::shared_ptr<N> node) const
+ {
+ return getEdges_(node, OUTGOING);
+ }
+
+ std::vector<EdgeIndex> getOutgoingEdges(NodeIndex node) const
+ {
+ return getEdgeIndexes(getOutgoingEdges(getNode(node)));
+ }
+
+ /**
+ * In an directed graph, get all the neighbors which
+ * are coming to a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the incoming neighbors
+ */
+
+ std::vector<std::shared_ptr<N> > getIncomingNeighbors(const std::shared_ptr<N> node) const
+ {
+ return getNeighbors_(node, INCOMING);
+ }
+
+ std::vector<NodeIndex> getIncomingNeighbors(NodeIndex node) const
+ {
+ return getNodeIndexes(getIncomingNeighbors(getNode(node)));
+ }
+
+
+ /**
+ * In an directed graph, get all the edges which
+ * are coming to a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the incoming edges
+ */
+
+ std::vector<std::shared_ptr<E> > getIncomingEdges(const std::shared_ptr<N> node) const
+ {
+ return getEdges_(node, INCOMING);
+ }
+
+ std::vector<EdgeIndex> getIncomingEdges(NodeIndex node) const
+ {
+ return getEdgeIndexes(getIncomingEdges(getNode(node)));
+ }
+
+ /**
+ * Get the leaves of a graph, ie, nodes with only one neighbor,
+ * starting from a peculiar node, with maxDepth recursion depths.
+ *
+ * @param node the starting node
+ * @param maxDepth the max recursion depth
+ * @return a vector containing the leaves
+ */
+
+ std::vector<std::shared_ptr<N> > getLeavesFromNode(std::shared_ptr<N> node, unsigned int maxDepth) const
+ {
+ return getNodesFromGraphid(getGraph()->getLeavesFromNode(getNodeGraphid(node), maxDepth));
+ }
+
+ /**
+ * Get all the leaves objects of a graph, ie, nodes with only one neighbor,
+ * @return a vector containing the leaves
+ */
+
+ std::vector<std::shared_ptr<N> > getAllLeaves() const
+ {
+ std::vector<std::shared_ptr<N> > leavesToReturn;
+ // fetching all the graph Leaves
+ std::vector<NodeGraphid> graphLeaves = getGraph()->getAllLeaves();
+ // testing if they are defined in this observer
+ for (typename std::vector<NodeGraphid>::iterator currGraphLeave = graphLeaves.begin(); currGraphLeave != graphLeaves.end(); currGraphLeave++)
+ {
+ std::shared_ptr<N> foundLeafObject = graphidToN_.at(*currGraphLeave);
+ if (foundLeafObject != 00)
+ leavesToReturn.push_back(foundLeafObject);
+ }
+ return leavesToReturn;
+ }
+
+ /**
+ * Get all the inner nodes of a graph, ie, nodes with degree >= 2.
+ * @return a vector containing the inner nodes.
+ */
+
+ virtual std::vector<std::shared_ptr<N> > getAllInnerNodes() const
+ {
+ std::vector<std::shared_ptr<N> > nodesToReturn;
+ // fetching all the graph Leaves
+ std::vector<NodeGraphid> graphNodes = getGraph()->getAllInnerNodes();
+ // testing if they are defined in this observer
+ for (typename std::vector<NodeGraphid>::iterator currGraphNode = graphNodes.begin(); currGraphNode != graphNodes.end(); currGraphNode++)
+ {
+ std::shared_ptr<N> foundNodeObject = graphidToN_.at(*currGraphNode);
+ if (foundNodeObject != 00)
+ nodesToReturn.push_back(foundNodeObject);
+ }
+ return nodesToReturn;
+ }
+
+ /**
+ * Get all the defined nodes of a graph,
+ * @return a vector containing the nodesObjects
+ */
+
+ std::vector<std::shared_ptr<N> > getAllNodes() const
+ {
+ std::vector<std::shared_ptr<N> > nodesToReturn;
+ for (typename std::vector<std::shared_ptr<N> >::const_iterator currNodeObject = graphidToN_.begin(); currNodeObject != graphidToN_.end(); currNodeObject++)
+ {
+ if (*currNodeObject != 00)
+ {
+ nodesToReturn.push_back(*currNodeObject);
+ }
+ }
+ return nodesToReturn;
+ }
+
+ std::vector<NodeIndex> getAllNodesIndexes() const
+ {
+ std::vector<typename AssociationGraphObserver<N, E>::NodeIndex > indexesToReturn;
+ for (typename std::vector<std::shared_ptr<N> >::const_iterator currNodeObject = graphidToN_.begin(); currNodeObject != graphidToN_.end(); currNodeObject++)
+ {
+ if (*currNodeObject != 00)
+ {
+ indexesToReturn.push_back(getNodeIndex(*currNodeObject));
+ }
+ }
+ return indexesToReturn;
+ }
+
+
+ template<class GraphIterator, bool is_const>
+ class EdgeIteratorClass :
+ public AssociationGraphObserver<N, E>::EdgeIterator
+ {
+private:
+ EdgesIteratorClass<GraphIterator, is_const> it_;
+ const AssociationGraphImplObserver<N, E, GraphImpl>& agio_;
+
+public:
+ EdgeIteratorClass<GraphIterator, is_const>(AssociationGraphImplObserver<N, E, GraphImpl> &agio) : it_(*agio.getGraph()),
+ agio_(agio) { start(); };
+
+ EdgeIteratorClass<GraphIterator, is_const>(AssociationGraphImplObserver<N, E, GraphImpl> &agio, std::shared_ptr<N> n) : it_(*agio.getGraph(), agio.getNodeGraphid(n)),
+ agio_(agio) { start(); };
+
+ EdgeIteratorClass<GraphIterator, is_const>(const AssociationGraphImplObserver<N, E, GraphImpl> &agio) : it_(*agio.getGraph()),
+ agio_(agio) { start(); };
+
+ EdgeIteratorClass<GraphIterator, is_const>(const AssociationGraphImplObserver<N, E, GraphImpl> &agio, std::shared_ptr<N> n) : it_(*agio.getGraph(), agio.getNodeGraphid(n)),
+ agio_(agio) { start(); };
+
+ ~EdgeIteratorClass<GraphIterator, is_const>() {}
+
+ void next() {it_.next(); while (!it_.end() && (agio_.getEdgeFromGraphid(*it_) == 0)) it_.next(); }
+
+ bool end() const {return it_.end(); }
+
+ void start() { it_.start(); while (!it_.end() && (agio_.getEdgeFromGraphid(*it_) == 0)) it_.next(); }
+
+ std::shared_ptr<E> operator*() {return agio_.getEdgeFromGraphid(*it_); }
+ };
+
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::EdgeIterator> allEdgesIterator()
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::ALLGRAPHITER, false> >(new AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::ALLGRAPHITER, false>(*this));
+ }
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::EdgeIterator> allEdgesIterator() const
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::ALLGRAPHITER, true> >(new AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::ALLGRAPHITER, true>(*this));
+ }
+
+ /*
+ * @brief builds iterator on the outgoing neighbor nodes of a Edge
+ *
+ */
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::EdgeIterator> outgoingEdgesIterator(std::shared_ptr<N> node)
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::OUTGOINGNEIGHBORITER, false> >(new AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::OUTGOINGNEIGHBORITER, false>(*this, node));
+ }
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::EdgeIterator> outgoingEdgesIterator(std::shared_ptr<N> node) const
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::OUTGOINGNEIGHBORITER, true> >(new AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::OUTGOINGNEIGHBORITER, true>(*this, node));
+ }
+
+ /*
+ * @brief builds iterator on the incoming neighbor nodes of a Edge
+ *
+ */
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::EdgeIterator> incomingEdgesIterator(std::shared_ptr<N> node)
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::INCOMINGNEIGHBORITER, false> >(new AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::INCOMINGNEIGHBORITER, false>(*this, node));
+ }
+
+ std::unique_ptr<typename AssociationGraphObserver<N, E>::EdgeIterator> incomingEdgesIterator(std::shared_ptr<N> node) const
+ {
+ return std::unique_ptr<AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::INCOMINGNEIGHBORITER, true> >(new AssociationGraphImplObserver<N, E, GraphImpl>::EdgeIteratorClass<Graph::INCOMINGNEIGHBORITER, true>(*this, node));
+ }
+
+ /**
+ * Get all the defined branches of a graph,
+ * @return a vector containing the branchesObjects
+ */
+
+ std::vector<std::shared_ptr<E> > getAllEdges() const
+ {
+ std::vector<std::shared_ptr<E> > branchesToReturn;
+ for (typename std::vector<std::shared_ptr<E> >::const_iterator currBrObject = graphidToE_.begin(); currBrObject != graphidToE_.end(); currBrObject++)
+ {
+ if (*currBrObject != 00)
+ {
+ branchesToReturn.push_back(*currBrObject);
+ }
+ }
+ return branchesToReturn;
+ }
+
+ /**
+ * @brief Is the node a leaf?
+ */
+ bool isLeaf(const std::shared_ptr<N> node) const
+ {
+ return getGraph()->isLeaf(this->getNodeGraphid(node));
+ }
+
+ /**
+ * Get nodes located at the extremities of an edge
+ * @param edge an edge
+ * @return a pair of the Nodes at each extremity of the edge
+ * example : N1--E1-->N2; getNodes(E1) will return (N1,N2);
+ */
+
+ std::pair<std::shared_ptr<N>, std::shared_ptr<N> > getNodes(std::shared_ptr<E> edge) const
+ {
+ std::pair<NodeGraphid, NodeGraphid> nodes = getGraph()->getNodes(getEdgeGraphid(edge));
+ return std::pair<std::shared_ptr<N>, std::shared_ptr<N> >(getNodeFromGraphid(nodes.first), getNodeFromGraphid(nodes.second));
+ }
+
+ /**
+ * Returns the Edge between two nodes nodeA -> nodeB
+ * @param nodeA source node (if directed)
+ * @param nodeB destination node (if directed)
+ * @return the edge between these two nodes
+ */
+
+ std::shared_ptr<E> getEdgeLinking(std::shared_ptr<N> nodeA, std::shared_ptr<N> nodeB) const
+ {
+ return getEdgeFromGraphid(getGraph()->getEdge(getNodeGraphid(nodeA), getNodeGraphid(nodeB)));
+ }
+
+ /**
+ * Sets the Edge between two nodes nodeA -> nodeB
+ * @param nodeA source node (if directed)
+ * @param nodeB destination node (if directed)
+ * @param edge the edge between these two nodes
+ */
+ void setEdgeLinking(std::shared_ptr<N> nodeA, std::shared_ptr<N> nodeB, std::shared_ptr<E> edge)
+ {
+ associateEdge(edge, getGraph()->getEdge(getNodeGraphid(nodeA), getNodeGraphid(nodeB)));
+ }
+
+ // /@}
+
+
+ /** @name Function called by the subjectGraph
+ * These methodes are called by the subject graph to make this observer so fit the subject graph
+ */
+ // /@{
+
+ /**
+ * Delete unused object edges, since they have been deleted in the graph
+ * @param edgesToDelete a vector of Edges to delete
+ */
+ void deletedEdgesUpdate(const std::vector< unsigned int >& edgesToDelete)
+ {
+ for (typename std::vector<EdgeGraphid>::const_iterator currEdge = edgesToDelete.begin(); currEdge != edgesToDelete.end(); currEdge++)
+ {
+ if (graphidToE_.size() > *currEdge)
+ {
+ std::shared_ptr<E> edgeObject = graphidToE_.at(*currEdge);
+ graphidToE_.at(*currEdge) = 00;
+
+ EToGraphid_.erase(edgeObject);
+ }
+ }
+ }
+
+ /**
+ * Delete unused object nodes, since they have been deleted in the graph
+ * @param nodesToDelete a vector of N to delete
+ */
+ void deletedNodesUpdate(const std::vector< unsigned int >& nodesToDelete)
+ {
+ for (typename std::vector<EdgeGraphid>::const_iterator currNode = nodesToDelete.begin(); currNode != nodesToDelete.end(); currNode++)
+ {
+ if (graphidToN_.size() > *currNode)
+ {
+ std::shared_ptr<N> nodeObject = graphidToN_.at(*currNode);
+ graphidToN_.at(*currNode) = 00;
+
+ NToGraphid_.erase(nodeObject);
+ }
+ }
+ }
+
+ // /@}
+
+ /** @name General Info
+ * General information about the graph
+ */
+ // /@{
+
+ /**
+ * Return the number of defined nodes, ie nodes that have a corresponding object
+ * in this GraphObserver
+ * @return the number of nodes
+ */
+ size_t getNumberOfNodes() const
+ {
+ return NToGraphid_.size();
+ }
+
+ /**
+ * Return the number of defined edges, ie edges that have a corresponding object
+ * in this GraphObserver
+ * @return the number of edges
+ */
+ size_t getNumberOfEdges() const
+ {
+ return EToGraphid_.size();
+ }
+
+
+ /**
+ * Return the number of defined leaves, ie leaves that have a corresponding object
+ * in this GraphObserver
+ * @return the number of leaves
+ */
+ size_t getNumberOfLeaves() const
+ {
+ size_t nb = 0;
+ for (typename std::vector<std::shared_ptr<N> >::const_iterator currNodeObject = graphidToN_.begin(); currNodeObject != graphidToN_.end(); currNodeObject++)
+ {
+ if ((*currNodeObject != 00) && (isLeaf(*currNodeObject)))
+ nb++;
+ }
+
+ return nb;
+ }
+
+ /**
+ * Return the number of neighbors of a node
+ * @param node the concerned node
+ * @return the number of neighbors
+ */
+ size_t getDegree(const std::shared_ptr<N> node) const
+ {
+ return getGraph()->getDegree(getNodeGraphid(node));
+ }
+
+ // /@}
+
+ template<typename N2, typename E2, typename G2> friend class AssociationGraphImplObserver;
+};
+
+/***************/
+
+template<class N, class E>
+using AssociationGlobalGraphObserver = AssociationGraphImplObserver<N, E, GlobalGraph>;
+}
+
+#endif
diff --git a/src/Bpp/Graph/AssociationGraphObserver.h b/src/Bpp/Graph/AssociationGraphObserver.h
new file mode 100644
index 0000000..1788f3f
--- /dev/null
+++ b/src/Bpp/Graph/AssociationGraphObserver.h
@@ -0,0 +1,483 @@
+//
+// File AssociationGraphObserver.h
+// Created by: Thomas Bigot
+// Last modification : vendredi 4 novembre 2016, à 10h 21
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _ASSOCIATIONGRAPHOBSERVER_HPP_
+#define _ASSOCIATIONGRAPHOBSERVER_HPP_
+
+#include "GraphObserver.h"
+
+#include "../Exceptions.h"
+#include "../Clonable.h"
+
+#include <vector>
+#include <map>
+#include <iostream>
+#include <ostream>
+#include <memory>
+#include <type_traits>
+
+namespace bpp
+{
+/**
+ * @brief Defines a Graph Associator. It is a template which follows
+ * (subscribed to) a Graph.
+ *
+ * @author Thomas Bigot, Laurent Guéguen
+ */
+
+template<class N, class E>
+class AssociationGraphObserver :
+ public virtual GraphObserver
+{
+private:
+ typedef Graph::NodeId NodeGraphid;
+ typedef Graph::EdgeId EdgeGraphid;
+
+public:
+ typedef unsigned int NodeIndex;
+ typedef unsigned int EdgeIndex;
+
+ /**
+ * Specific copy of A and B objects, if clonable or not.
+ *
+ */
+
+ template<class A, class B>
+ static B* copy(const A& a, typename std::enable_if< !std::is_base_of<B, A>::value&& !std::is_abstract<B>::value>::type* = 0)
+ {
+ return new B(a);
+ }
+
+ template<class A, class B>
+ static B* copy(const A& a, typename std::enable_if< std::is_base_of<B, A>::value&& !std::is_abstract<A>::value>::type* = 0)
+ {
+ return dynamic_cast<B*>(new A(a));
+ }
+
+ template<class A, class B>
+ static B* copy(const A& a, typename std::enable_if< std::is_base_of<B, A>::value&& std::is_abstract<A>::value&& std::is_base_of<Clonable, A>::value>::type* = 0)
+ {
+ return dynamic_cast<B*>(a.clone());
+ }
+
+
+ /** @name Graph Relations Management
+ * Modificating the structure of the graph.
+ */
+ // /@{
+
+ /**
+ * Creates an orphaned node from a NodeClass object.
+ * @param newNodeObject the N object associated to the node in the graph.
+ *
+ */
+ virtual void createNode(std::shared_ptr<N> newNodeObject) = 0;
+
+
+ /**
+ * Creates an node linked to an existing node. Order of parameters match
+ * the link method.
+ * @param newNodeObject the N object associated to the node in the graph.
+ * @param objectOriginNode existing node. In a directed graph:
+ * origin -> newNode.
+ * @param newEdgeObject optional edge between nodes (default = 00)
+ */
+
+ virtual void createNode(std::shared_ptr<N> objectOriginNode, std::shared_ptr<N> newNodeObject, std::shared_ptr<E> newEdgeObject = 00) = 0;
+
+ /**
+ * Creates a link between two existing nodes.
+ * If directed graph: nodeA -> nodeB.
+ * @param nodeObjectA source node (or first node if undirected)
+ * @param nodeObjectB target node (or second node if undirected)
+ * @param edgeObject the optional edge between the nodes (default
+ * = 00)
+ */
+
+ virtual void link(std::shared_ptr<N> nodeObjectA, std::shared_ptr<N> nodeObjectB, std::shared_ptr<E> edgeObject = 00) = 0;
+
+ /**
+ * Detroys a link between two existing nodes in the graph.
+ * If directed graph: nodeA -> nodeB.
+ * @param nodeObjectA source node (or first node if undirected)
+ * @param nodeObjectB target node (or second node if undirected)
+ */
+
+ virtual void unlink(std::shared_ptr<N> nodeObjectA, std::shared_ptr<N> nodeObjectB) = 0;
+
+ /**
+ * Deletes a node
+ * @param nodeObject node to be deleted
+ */
+ virtual void deleteNode(std::shared_ptr<N> nodeObject) = 0;
+
+ // /@}
+
+ /** @name Object Association
+ * Associate or dissociate N and E objects to pre-existing Graph Nodes and Graph Edges
+ */
+ // /@{
+
+ /**
+ * Associate a N object to a node in the graph.
+ * @param nodeObject object to associate
+ * @param node existing node to be associated
+ */
+
+ virtual void associateNode(std::shared_ptr<N> nodeObject, NodeGraphid node) = 0;
+
+ /**
+ * Associate a E object to an edge in the graph.
+ * @param edgeObject object to associate
+ * @param edge existing edge to be associated
+ */
+
+ virtual void associateEdge(std::shared_ptr<E> edgeObject, EdgeGraphid edge) = 0;
+
+ /**
+ * Dissociate a N or E object to a node or an edge in the graph.
+ * Graph is not changed.
+ *
+ * @param nodeObject object to dissociate
+ */
+
+ virtual void dissociateNode(std::shared_ptr<N> nodeObject) = 0;
+ virtual void dissociateEdge(std::shared_ptr<E> edgeObject) = 0;
+
+
+ /**
+ * Return the associated Node ID
+ * @param nodeObject object which to return the node ID
+ * @return a node ID
+ */
+ virtual NodeGraphid getNodeGraphid(const std::shared_ptr<N> nodeObject) const = 0;
+
+ /**
+ * Return the associated Node ID
+ * @param edgeObject object which to return the node ID
+ * @return a node ID
+ */
+ virtual EdgeGraphid getEdgeGraphid(const std::shared_ptr<E> edgeObject) const = 0;
+
+ /**
+ * Transforms an (a list of) id(s) into an (a list of) object(s)
+ */
+ virtual const std::shared_ptr<N> getNodeFromGraphid(NodeGraphid) const = 0;
+ virtual std::shared_ptr<N> getNodeFromGraphid(NodeGraphid) = 0;
+
+ virtual std::vector<std::shared_ptr<N> > getNodesFromGraphid(std::vector<NodeGraphid> ) const = 0;
+ virtual std::shared_ptr<E> getEdgeFromGraphid(EdgeGraphid) = 0;
+ virtual const std::shared_ptr<E> getEdgeFromGraphid(EdgeGraphid) const = 0;
+ virtual std::vector<std::shared_ptr<E> > getEdgesFromGraphid(std::vector<EdgeGraphid> ) const = 0;
+
+
+ /**
+ * @return the root
+ */
+
+ virtual std::shared_ptr<N> getRoot() const = 0;
+
+ virtual NodeIndex getRootIndex() const = 0;
+
+ // /@}
+
+
+ /** @name Object Indexation
+ * Get or set indexes to nodes and edges
+ */
+ // /@{
+
+ /**
+ * @brief return if the object has an index.
+ */
+
+ virtual bool hasIndex(const std::shared_ptr<N> nodeObject) const = 0;
+ virtual bool hasIndex(const std::shared_ptr<E> edgeObject) const = 0;
+
+ /**
+ * Return the associated Node index
+ * @param nodeObject object which to return the node index
+ * @return a node index
+ */
+
+ virtual NodeIndex getNodeIndex(const std::shared_ptr<N> nodeObject) const = 0;
+ virtual std::vector<NodeIndex> getNodeIndexes(std::vector<std::shared_ptr<N> > nodeObjects) const = 0;
+
+
+ /**
+ * Return the associated Node index
+ * @param edgeObject object which to return the node index
+ * @return a node index
+ */
+ virtual EdgeIndex getEdgeIndex(const std::shared_ptr<E> edgeObject) const = 0;
+ virtual std::vector<EdgeIndex> getEdgeIndexes(std::vector<std::shared_ptr<E> > edgeObjects) const = 0;
+
+ /**
+ * Set an index associated to a node
+ * @param nodeObject object to which one want to set the index
+ * @param index intex to be given, 0 to get the first free index
+ * @return the given index
+ */
+ virtual NodeIndex setNodeIndex(const std::shared_ptr<N> nodeObject, NodeIndex index) = 0;
+
+ /**
+ * Set an index associated to an edge
+ * @param edgeObject object to which one want to set the index
+ * @param index intex to be given, 0 to get the first free index
+ * @return the given index
+ */
+ virtual EdgeIndex setEdgeIndex(const std::shared_ptr<E> edgeObject, EdgeIndex index) = 0;
+
+ /**
+ * Return the associated Node, querying with an index
+ * @param nodeIndex the index of the wanted node
+ * @return N, a node object
+ */
+
+ virtual std::shared_ptr<N> getNode(NodeIndex nodeIndex) const = 0;
+
+ /**
+ * Return the associated Node index
+ * @param edgeIndex the index of the wanted edge
+ * @return E, an edge object
+ */
+ virtual std::shared_ptr<E> getEdge(EdgeIndex edgeIndex) const = 0;
+
+ // /@}
+
+ /** @name Topology exploration
+ * These methodes of the graph concern the topology exploration.
+ */
+ // /@{
+
+ /**
+ * @name Iterator interface on Nodes
+ *
+ */
+
+ class NodeIterator
+ {
+public:
+ virtual ~NodeIterator() {}
+
+ virtual void next() = 0;
+ virtual bool end() const = 0;
+ virtual void start() = 0;
+
+ virtual std::shared_ptr<N> operator*() = 0;
+ };
+
+
+ /*
+ * @brief builds iterator on all Nodes of the graph
+ *
+ */
+
+ virtual std::unique_ptr<NodeIterator> allNodesIterator() = 0;
+
+ virtual std::unique_ptr<NodeIterator> allNodesIterator() const = 0;
+
+ /*
+ * @brief builds iterator on the outgoing neighbor nodes of a Node
+ *
+ */
+
+ virtual std::unique_ptr<NodeIterator> outgoingNeighborNodesIterator(std::shared_ptr<N> node) = 0;
+
+ virtual std::unique_ptr<NodeIterator> outgoingNeighborNodesIterator(std::shared_ptr<N> node) const = 0;
+
+ /*
+ * @brief builds iterator on the incoming neighbor nodes of a Node
+ *
+ */
+
+ virtual std::unique_ptr<NodeIterator> incomingNeighborNodesIterator(std::shared_ptr<N> node) = 0;
+
+ virtual std::unique_ptr<NodeIterator> incomingNeighborNodesIterator(std::shared_ptr<N> node) const = 0;
+
+ /**
+ * Get all the neighbors of a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the neighbors
+ */
+
+ virtual std::vector<std::shared_ptr<N> > getNeighbors(const std::shared_ptr<N> node) const = 0;
+ virtual std::vector<NodeIndex> getNeighbors(NodeIndex node) const = 0;
+
+ /**
+ * Get all the edges from/to a node in the graph.
+ * @param node the node one wants to get its neighbor edges
+ * @return a vector containing the edges
+ */
+ virtual std::vector<std::shared_ptr<E> > getEdges(const std::shared_ptr<N> node) const = 0;
+ virtual std::vector<EdgeIndex> getEdges(NodeIndex node) const = 0;
+
+ /**
+ * In an directed graph, get all the neighbors which
+ * are leaving a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the outgoing neighbors
+ */
+ virtual std::vector<std::shared_ptr<N> > getOutgoingNeighbors(const std::shared_ptr<N> node) const = 0;
+ virtual std::vector<NodeIndex> getOutgoingNeighbors(NodeIndex node) const = 0;
+
+ /**
+ * In an directed graph, get all the edges which
+ * are leaving a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the outgoing edges
+ */
+ virtual std::vector<std::shared_ptr<E> > getOutgoingEdges(const std::shared_ptr<N> node) const = 0;
+ virtual std::vector<EdgeIndex> getOutgoingEdges(NodeIndex node) const = 0;
+
+
+ /**
+ * In an directed graph, get all the neighbors which
+ * are coming to a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the incoming neighbors
+ */
+ virtual std::vector<std::shared_ptr<N> > getIncomingNeighbors(const std::shared_ptr<N> node) const = 0;
+ virtual std::vector<NodeIndex> getIncomingNeighbors(NodeIndex node) const = 0;
+
+ /**
+ * In an directed graph, get all the edges which
+ * are coming to a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the incoming edges
+ */
+ virtual std::vector<std::shared_ptr<E> > getIncomingEdges(const std::shared_ptr<N> node) const = 0;
+ virtual std::vector<EdgeIndex> getIncomingEdges(NodeIndex node) const = 0;
+
+
+ /**
+ * Get the leaves of a graph, ie, nodes with only one neighbor,
+ * starting from a peculiar node, up to a specific depth.
+ * @param node the starting node
+ * @param maxDepth the max recursion depth
+ * @return a vector containing the leaves
+ */
+ virtual std::vector<std::shared_ptr<N> > getLeavesFromNode(std::shared_ptr<N> node, unsigned int maxDepth) const = 0;
+
+ /**
+ * Get all the leaves objects of a graph, ie, nodes with only one neighbor,
+ * @return a vector containing the leaves
+ */
+ virtual std::vector<std::shared_ptr<N> > getAllLeaves() const = 0;
+
+ /**
+ * Get all the inner nodes of a graph, ie, nodes with degree >= 2.
+ * @return a vector containing the inner nodes.
+ */
+ virtual std::vector<std::shared_ptr<N> > getAllInnerNodes() const = 0;
+
+ /**
+ * Get all the defined nodes of a graphO,
+ * @return a vector containing the nodesObjects
+ */
+ virtual std::vector<std::shared_ptr<N> > getAllNodes() const = 0;
+ virtual std::vector<NodeIndex> getAllNodesIndexes() const = 0;
+
+ /**
+ * @name Iterator interface on Edges
+ *
+ */
+
+ class EdgeIterator
+ {
+public:
+ virtual ~EdgeIterator() {}
+
+ virtual void next() = 0;
+ virtual bool end() const = 0;
+ virtual void start() = 0;
+
+ virtual std::shared_ptr<E> operator*() = 0;
+ };
+
+
+ /*
+ * @brief builds iterator on all Nodes of the graph
+ *
+ */
+
+ virtual std::unique_ptr<EdgeIterator> allEdgesIterator() = 0;
+
+ /*
+ * @brief builds iterator on the outgoing neighbor nodes of a Node
+ *
+ */
+
+ virtual std::unique_ptr<EdgeIterator> outgoingEdgesIterator(std::shared_ptr<N> node) = 0;
+
+ /*
+ * @brief builds iterator on the incoming neighbor nodes of a Node
+ *
+ */
+
+ virtual std::unique_ptr<EdgeIterator> incomingEdgesIterator(std::shared_ptr<N> node) = 0;
+
+ /**
+ * Get all the defined edges of a graphO,
+ * @return a vector containing the branchesObjects
+ */
+
+ virtual std::vector<std::shared_ptr<E> > getAllEdges() const = 0;
+
+ /**
+ * Returns the Edge between two nodes nodeA -> nodeB
+ * @param nodeA source node (if directed)
+ * @param nodeB destination node (if directed)
+ * @return the edge between these two nodes
+ */
+ virtual std::shared_ptr<E> getEdgeLinking(std::shared_ptr<N> nodeA, std::shared_ptr<N> nodeB) const = 0;
+
+ /**
+ * Sets the Edge between two nodes nodeA -> nodeB
+ * @param nodeA source node (if directed)
+ * @param nodeB destination node (if directed)
+ * @param edge the edge between these two nodes
+ */
+ virtual void setEdgeLinking(std::shared_ptr<N> nodeA, std::shared_ptr<N> nodeB, std::shared_ptr<E> edge) = 0;
+
+ // /@}
+};
+}
+
+#endif
diff --git a/src/Bpp/Graph/AssociationTreeGraphImplObserver.h b/src/Bpp/Graph/AssociationTreeGraphImplObserver.h
new file mode 100644
index 0000000..48cb98c
--- /dev/null
+++ b/src/Bpp/Graph/AssociationTreeGraphImplObserver.h
@@ -0,0 +1,397 @@
+//
+// File AssociationTreeGraphImplObserver.h
+// Created by: Thomas Bigot
+// Last modification : vendredi 4 novembre 2016, à 10h 21
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _ASSOCIATION_TREEGRAPH_IMPL_OBSERVER_HPP_
+#define _ASSOCIATION_TREEGRAPH_IMPL_OBSERVER_HPP_
+
+#include "TreeGraphImpl.h"
+#include "AssociationTreeGraphObserver.h"
+#include "AssociationGraphImplObserver.h"
+
+#include <vector>
+#include <map>
+#include <iostream>
+#include <ostream>
+#include <memory>
+
+namespace bpp
+{
+template<class N, class E, class TreeGraphImpl>
+class AssociationTreeGraphImplObserver :
+ public AssociationTreeGraphObserver<N, E>,
+ public AssociationGraphImplObserver<N, E, TreeGraphImpl>
+{
+public:
+ typedef typename AssociationGraphObserver<N, E>::NodeIndex NodeIndex;
+ typedef typename AssociationGraphObserver<N, E>::EdgeIndex EdgeIndex;
+
+ typedef typename Graph::NodeId NodeGraphid;
+ typedef typename Graph::EdgeId EdgeGraphid;
+
+public:
+ /**
+ * Constructor
+ * @param rooted if the graph rooted
+ */
+ AssociationTreeGraphImplObserver(bool rooted = false) :
+ AssociationGraphImplObserver<N, E, TreeGraphImpl>(rooted)
+ {}
+
+ /**
+ * Constructor
+ * @param subjectTreeGraph the graph which is observed
+ */
+ AssociationTreeGraphImplObserver(std::shared_ptr<TreeGraphImpl> subjectTreeGraph = 00) :
+ AssociationGraphImplObserver<N, E, TreeGraphImpl>(subjectTreeGraph)
+ {}
+
+ /**
+ * Copy Constructor
+ * @param treeGraphObserver the treeGraphObserver to be copied
+ */
+
+ AssociationTreeGraphImplObserver(bpp::AssociationTreeGraphImplObserver<N, E, TreeGraphImpl> const& treeGraphObserver) :
+ AssociationGraphImplObserver<N, E, TreeGraphImpl>(treeGraphObserver)
+ {}
+
+ /**
+ * Copy Constructor
+ * @param treeGraphObserver the treeGraphObserver to be copied
+ */
+
+ template<class N2, class E2>
+ AssociationTreeGraphImplObserver(bpp::AssociationTreeGraphImplObserver<N2, E2, TreeGraphImpl> const& treeGraphObserver) :
+ AssociationGraphImplObserver<N, E, TreeGraphImpl>::AssociationGraphImplObserver(treeGraphObserver)
+ {}
+
+
+ /**
+ * = Operator
+ * @param treeGraphObserver the treeGraphObserver we want to copy the values
+ */
+
+ AssociationTreeGraphImplObserver<N, E, TreeGraphImpl>& operator=(bpp::AssociationTreeGraphImplObserver<N, E, TreeGraphImpl> const& treeGraphObserver)
+ {
+ AssociationGraphImplObserver<N, E, TreeGraphImpl>::operator=(treeGraphObserver);
+ return *this;
+ }
+
+
+ /**
+ * Destructor
+ */
+
+ ~AssociationTreeGraphImplObserver()
+ {}
+
+
+ /**
+ * clone function
+ */
+ AssociationTreeGraphImplObserver<N, E, TreeGraphImpl>* clone() const { return new AssociationTreeGraphImplObserver<N, E, TreeGraphImpl>(*this); }
+
+
+ /**
+ * Is the graph a tree? A tree must be acyclic and with no isolated node.
+ * @return true if valid tree
+ */
+ bool isValid() const
+ {
+ return this->getGraph()->isValid();
+ }
+
+ /**
+ * Return, in a rooted tree, the branch leading to the father
+ * @param nodeObject the concerned node
+ * @return an Edge which is the branch to the father
+ */
+ std::shared_ptr<E> getEdgeToFather(const std::shared_ptr<N> nodeObject) const
+ {
+ return this->getEdgeFromGraphid(this->getGraph()->getEdgeToFather(this->getNodeGraphid(nodeObject)));
+ }
+
+ std::shared_ptr<E> getEdgeToFather(const NodeIndex index) const
+ {
+ return this->getEdgeFromGraphid(this->getGraph()->getEdgeToFather(this->getNodeGraphid(this->getNode(index))));
+ }
+
+
+ /**
+ * @brief Sets the root and make the tree directed from root to leaves
+ *
+ */
+ void rootAt(const std::shared_ptr<N> root)
+ {
+ this->getGraph()->rootAt(this->getNodeGraphid(root));
+ }
+
+ /*
+ * @brief check if rooted, ie directed
+ *
+ */
+ bool isRooted() const
+ {
+ return this->getGraph()->isRooted();
+ }
+
+ /**
+ * Return, in a rooted tree, the father node
+ * @param nodeObject the concerned node
+ * @return the father
+ */
+
+ std::shared_ptr<N> getFather(const std::shared_ptr<N> nodeObject) const
+ {
+ return this->getNodeFromGraphid(this->getGraph()->getFather(this->getNodeGraphid(nodeObject)));
+ }
+
+ /**
+ * Has the node a father?
+ */
+ bool hasFather(const std::shared_ptr<N> nodeObject) const
+ {
+ return this->getGraph()->hasFather(this->getNodeGraphid(nodeObject));
+ }
+
+ bool hasFather(const NodeIndex index) const
+ {
+ return this->getGraph()->hasFather(this->getNodeGraphid(this->getNode(index)));
+ }
+
+ /**
+ * Return, in a rooted tree, the sons of a node
+ * @param node the concerned node
+ * @return a vector of son Nodes
+ */
+
+ std::vector<std::shared_ptr<N> > getSons(const std::shared_ptr<N> node) const
+ {
+ return this->getNodesFromGraphid(this->getGraph()->getSons(this->getNodeGraphid(node)));
+ }
+
+ std::vector<NodeIndex> getSons(const NodeIndex node) const
+ {
+ return this->getNodeIndexes(this->getNodesFromGraphid(this->getGraph()->getSons(this->getNodeGraphid(this->getNode(node)))));
+ }
+
+ /**
+ * Return, in a rooted tree, the branches to the sons of a node
+ * @param node the concerned node
+ * @return a vector of branch Nodes
+ */
+
+ std::vector<std::shared_ptr<E> > getBranches(const std::shared_ptr<N> node) const
+ {
+ return this->getEdgesFromGraphid(this->getGraph()->getBranches(this->getNodeGraphid(node)));
+ }
+
+ std::vector<EdgeIndex> getBranches(const NodeIndex node) const
+ {
+ return this->getEdgeIndexes(this->getEdgesFromGraphid(this->getGraph()->getBranches(this->getNodeGraphid(this->getNode(node)))));
+ }
+
+ /**
+ * Return, in a rooted tree, the son of an edge
+ * @param edge the concerned edge
+ * @return the son Node
+ */
+
+ std::shared_ptr<N> getSon(const std::shared_ptr<E> edge) const
+ {
+ return this->getNodeFromGraphid(this->getGraph()->getBottom(this->getEdgeGraphid(edge)));
+ }
+
+ NodeIndex getSon(const EdgeIndex edge) const
+ {
+ return this->getNodeIndex(this->getNode(this->getGraph()->getBottom(this->getEdgeGraphid(this->getEdge(edge)))));
+ }
+
+ /**
+ * Return, in a rooted tree, the father of an edge
+ * @param edge the concerned edge
+ * @return the father Node
+ */
+
+ std::shared_ptr<N> getFather(const std::shared_ptr<E> edge) const
+ {
+ return this->getNodeFromGraphid(this->getGraph()->getTop(this->getEdgeGraphid(edge)));
+ }
+
+ NodeIndex getFather(const EdgeIndex edge) const
+ {
+ return this->getNodeIndex(this->getNode(this->getGraph()->getTop(this->getEdgeGraphid(this->getEdge(edge)))));
+ }
+
+
+ /**
+ * Return, in a rooted tree, the number of sons
+ * @param node the concerned node
+ * @return the number of sons
+ */
+ size_t getNumberOfSons(const std::shared_ptr<N> node) const
+ {
+ return this->getGraph()->getNumberOfSons(this->getNodeGraphid(node));
+ }
+
+ /**
+ * Get the leaves of a tree under a peculiar node.
+ *
+ * @param node the starting node
+ * @return a vector containing the leaves
+ */
+
+ std::vector<std::shared_ptr<N> > getLeavesUnderNode(std::shared_ptr<N> node) const
+ {
+ return this->getNodesFromGraphid(this->getGraph()->getLeavesUnderNode(this->getNodeGraphid(node)));
+ }
+
+
+ /**
+ * Remove the sons of a node
+ * @return a vector containing the removed nodes
+ */
+
+ std::vector<std::shared_ptr<N> > removeSons(const std::shared_ptr<N> node)
+ {
+ return this->getNodesFromGraphid(this->getGraph()->removeSons(this->getNodeGraphid(node)));
+ }
+
+ /**
+ * Remove a son of a node
+ */
+ void removeSon(const std::shared_ptr<N> node, const std::shared_ptr<N> son)
+ {
+ this->getGraph()->removeSon(this->getNodeGraphid(node), this->getNodeGraphid(son));
+ }
+
+ /**
+ * Change / set the father of a node
+ * @param nodeObject the concerned node
+ * @param fatherNodeObject the node to be the father
+ * @param edgeObject the optional edge between the nodes (default
+ * = 00)
+ */
+ void setFather(const std::shared_ptr<N> nodeObject, const std::shared_ptr<N> fatherNodeObject, const std::shared_ptr<E> edgeObject = 0)
+ {
+ if (edgeObject)
+ this->getGraph()->setFather(this->getNodeGraphid(nodeObject), this->getNodeGraphid(fatherNodeObject), this->getEdgeGraphid(edgeObject));
+ else
+ this->getGraph()->setFather(this->getNodeGraphid(nodeObject), this->getNodeGraphid(fatherNodeObject));
+ }
+
+
+ /**
+ * Add a son to a node
+ * @param nodeObject the concerned node
+ * @param sonNodeObject the node to be added as a son to the father
+ * @param edgeObject the optional edge between the nodes (default
+ * = 00)
+ */
+ void addSon(const std::shared_ptr<N> nodeObject, const std::shared_ptr<N> sonNodeObject, const std::shared_ptr<E> edgeObject = 0)
+ {
+ if (edgeObject)
+ this->getGraph()->addSon(this->getNodeGraphid(nodeObject), this->getNodeGraphid(sonNodeObject), this->getEdgeGraphid(edgeObject));
+ else
+ this->getGraph()->addSon(this->getNodeGraphid(nodeObject), this->getNodeGraphid(sonNodeObject));
+ }
+
+ /**
+ * Iterators
+ *
+ */
+
+ /*
+ * @brief builds iterator on the sons of a Node
+ *
+ */
+
+ std::unique_ptr<typename AssociationTreeGraphObserver<N, E>::NodeIterator> sonsIterator(std::shared_ptr<N> node)
+ {
+ return this->outgoingNeighborNodesIterator(node);
+ }
+
+ /*
+ * @brief builds iterator on the branches to sons of a Node
+ *
+ */
+
+ std::unique_ptr<typename AssociationTreeGraphObserver<N, E>::EdgeIterator> branchesIterator(std::shared_ptr<N> node)
+ {
+ return this->outgoingEdgesIterator(node);
+ }
+
+ /**
+ * @brief Get a vector of ancestor nodes between to nodes.
+ *
+ * @param nodeA first node.
+ * @param nodeB second node.
+ * @param includeAncestor Tell if the common ancestor must be included in the vector.
+ * @return A vector of ancestor nodes ids.
+ * @throw PhyloNodeNotFoundException If a node is not found.
+ */
+
+ std::vector<std::shared_ptr<N> > getNodePathBetweenTwoNodes(const std::shared_ptr<N> nodeA, const std::shared_ptr<N> nodeB, bool includeAncestor = true) const
+ {
+ return this->getNodesFromGraphid(this->getGraph()->getNodePathBetweenTwoNodes(this->getNodeGraphid(nodeA), this->getNodeGraphid(nodeB), includeAncestor));
+ }
+
+ std::vector<std::shared_ptr<E> > getEdgePathBetweenTwoNodes(const std::shared_ptr<N> nodeA, const std::shared_ptr<N> nodeB) const
+ {
+ return this->getEdgesFromGraphid(this->getGraph()->getEdgePathBetweenTwoNodes(this->getNodeGraphid(nodeA), this->getNodeGraphid(nodeB)));
+ }
+
+ std::vector<std::shared_ptr<N> > getSubtreeNodes(const std::shared_ptr<N> localRoot)
+ {
+ return this->getNodesFromGraphid(this->getGraph()->getSubtreeNodes(this->getNodeGraphid(localRoot)));
+ }
+
+ std::vector<std::shared_ptr<E> > getSubtreeEdges(const std::shared_ptr<N> localRoot)
+ {
+ return AssociationGraphImplObserver<N, E, TreeGraphImpl>::getEdgesFromGraphid(this->getGraph()->getSubtreeEdges(this->getNodeGraphid(localRoot)));
+ }
+};
+
+/********************/
+
+template<class N, class E>
+using AssociationTreeGlobalGraphObserver = AssociationTreeGraphImplObserver<N, E, TreeGlobalGraph>;
+}
+
+
+#endif
diff --git a/src/Bpp/Graph/AssociationTreeGraphObserver.h b/src/Bpp/Graph/AssociationTreeGraphObserver.h
new file mode 100644
index 0000000..e748ed0
--- /dev/null
+++ b/src/Bpp/Graph/AssociationTreeGraphObserver.h
@@ -0,0 +1,255 @@
+//
+// File AssociationTreeGraphObserver.h
+// Created by: Thomas Bigot
+// Last modification : vendredi 4 novembre 2016, à 10h 21
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _ASSOCIATION_TREE_GRAPHOBSERVER_HPP_
+#define _ASSOCIATION_TREE_GRAPHOBSERVER_HPP_
+
+#include "TreeGraph.h"
+#include "AssociationGraphObserver.h"
+
+#include <vector>
+#include <map>
+#include <iostream>
+#include <ostream>
+#include <memory>
+
+namespace bpp
+{
+/**
+ * @brief Defines a Tree Graph Associator. It is a template which follows
+ * (subscribed to) a Graph.
+ *
+ * @author Thomas Bigot
+ */
+
+template<class N, class E>
+class AssociationTreeGraphObserver :
+ public virtual AssociationGraphObserver<N, E>
+{
+public:
+ typedef typename AssociationTreeGraphObserver<N, E>::NodeIndex NodeIndex;
+ typedef typename AssociationTreeGraphObserver<N, E>::EdgeIndex EdgeIndex;
+
+ typedef typename TreeGraph::NodeId NodeGraphid;
+ typedef typename TreeGraph::EdgeId EdgeGraphid;
+
+public:
+ /**
+ * Is the graph a tree? A tree must be acyclic and with no isolated node.
+ * @return true if valid tree
+ */
+
+ virtual bool isValid() const = 0;
+
+ /**
+ * Return, in a rooted tree, the branch leading to the father
+ * @param nodeObject the concerned node
+ * @return an Edge which is the branch to the father
+ */
+
+ virtual std::shared_ptr<E> getEdgeToFather(const std::shared_ptr<N> nodeObject) const = 0;
+
+ virtual std::shared_ptr<E> getEdgeToFather(const NodeIndex nodeIndex) const = 0;
+
+ /**
+ * @brief Sets the root and make the tree directed from root to leaves
+ *
+ */
+
+ virtual void rootAt(const std::shared_ptr<N> root) = 0;
+
+ /*
+ * @brief check if rooted, ie directed
+ *
+ */
+
+ virtual bool isRooted() const = 0;
+
+ /**
+ * Return, in a rooted tree, the father node
+ * @param nodeObject the concerned node
+ * @return the father
+ */
+
+ virtual std::shared_ptr<N> getFather(const std::shared_ptr<N> nodeObject) const = 0;
+
+ /**
+ * Has the node a father?
+ */
+
+ virtual bool hasFather(const std::shared_ptr<N> nodeObject) const = 0;
+ virtual bool hasFather(const NodeIndex node) const = 0;
+
+ /**
+ * Return, in a rooted tree, the sons of a node
+ * @param node the concerned node
+ * @return a vector of son Nodes
+ */
+
+ virtual std::vector<std::shared_ptr<N> > getSons(const std::shared_ptr<N> node) const = 0;
+
+ virtual std::vector<NodeIndex> getSons(const NodeIndex node) const = 0;
+
+ /**
+ * Return the branches to the sons of a node
+ * @param node the concerned node
+ * @return a vector of branch Nodes
+ */
+
+ virtual std::vector<std::shared_ptr<E> > getBranches(const std::shared_ptr<N> node) const = 0;
+
+ virtual std::vector<EdgeIndex> getBranches(const NodeIndex node) const = 0;
+
+ /**
+ * Return, in a rooted tree, the son of an edge
+ * @param edge the concerned edge
+ * @return the son Node
+ */
+
+ virtual std::shared_ptr<N> getSon(const std::shared_ptr<E> edge) const = 0;
+ virtual NodeIndex getSon(const EdgeIndex edge) const = 0;
+
+ /**
+ * Return, in a rooted tree, the father of an edge
+ * @param edge the concerned edge
+ * @return the father Node
+ */
+
+ virtual std::shared_ptr<N> getFather(const std::shared_ptr<E> edge) const = 0;
+ virtual NodeIndex getFather(const EdgeIndex edge) const = 0;
+
+ /**
+ * Return, in a rooted tree, the number of sons
+ * @param node the concerned node
+ * @return the number of sons
+ */
+
+ virtual size_t getNumberOfSons(const std::shared_ptr<N> node) const = 0;
+
+ /**
+ * Get the leaves of a tree under a peculiar node.
+ *
+ * @param node the starting node
+ * @return a vector containing the leaves
+ */
+
+ virtual std::vector<std::shared_ptr<N> > getLeavesUnderNode(std::shared_ptr<N> node) const = 0;
+
+ /**
+ * Remove the sons of a node
+ * @return a vector containing the removed nodes
+ */
+
+ virtual std::vector<std::shared_ptr<N> > removeSons(const std::shared_ptr<N> node) = 0;
+
+ /**
+ * Remove a son of a node
+ */
+
+ virtual void removeSon(const std::shared_ptr<N> node, const std::shared_ptr<N> son) = 0;
+
+ /**
+ * Change / set the father of a node
+ * @param nodeObject the concerned node
+ * @param fatherNodeObject the node to be the father
+ * @param edgeObject the optional edge between the nodes (default
+ * = 00)
+ */
+
+ virtual void setFather(const std::shared_ptr<N> nodeObject, const std::shared_ptr<N> fatherNodeObject, const std::shared_ptr<E> edgeObject = 0) = 0;
+
+ /**
+ * Add a son to a node
+ * @param nodeObject the concerned node
+ * @param sonNodeObject the node to be added as a son to the father
+ * @param edgeObject the optional edge between the nodes (default
+ * = 00)
+ */
+
+ virtual void addSon(const std::shared_ptr<N> nodeObject, const std::shared_ptr<N> sonNodeObject, const std::shared_ptr<E> edgeObject = 0) = 0;
+
+ /**
+ * Iterators
+ *
+ */
+
+ /*
+ * @brief builds iterator on the neighbor nodes of a Node
+ *
+ */
+
+ typedef typename AssociationGraphObserver<N, E>::NodeIterator NodeIterator;
+ typedef typename AssociationGraphObserver<N, E>::EdgeIterator EdgeIterator;
+
+
+ /*
+ * @brief builds iterator on the sons of a Node
+ *
+ */
+
+ virtual std::unique_ptr<NodeIterator> sonsIterator(std::shared_ptr<N> node) = 0;
+
+ /*
+ * @brief builds iterator on the branches to sons of a Node
+ *
+ */
+
+ virtual std::unique_ptr<EdgeIterator> branchesIterator(std::shared_ptr<N> node) = 0;
+
+ /**
+ * @brief Get a vector of ancestor nodes between to nodes.
+ *
+ * @param nodeA first node.
+ * @param nodeB second node.
+ * @param includeAncestor Tell if the common ancestor must be included in the vector.
+ * @return A vector of ancestor nodes ids.
+ * @throw PhyloNodeNotFoundException If a node is not found.
+ */
+
+ virtual std::vector<std::shared_ptr<N> > getNodePathBetweenTwoNodes(const std::shared_ptr<N> nodeA, const std::shared_ptr<N> nodeB, bool includeAncestor = true) const = 0;
+
+ virtual std::vector<std::shared_ptr<E> > getEdgePathBetweenTwoNodes(const std::shared_ptr<N> nodeA, const std::shared_ptr<N> nodeB) const = 0;
+
+ virtual std::vector<std::shared_ptr<N> > getSubtreeNodes(const std::shared_ptr<N> localRoot) = 0;
+
+ virtual std::vector<std::shared_ptr<E> > getSubtreeEdges(const std::shared_ptr<N> localRoot) = 0;
+};
+}
+
+#endif
diff --git a/src/Bpp/Graph/BasicTNode.cpp b/src/Bpp/Graph/BasicTNode.cpp
deleted file mode 100644
index 0872f54..0000000
--- a/src/Bpp/Graph/BasicTNode.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-//
-// File: BasicTNode.cpp
-// Author: Sylvain Gaillard
-// Created: 14/01/2011 14:59:07
-//
-
-/*
-Copyright or © or Copr. Bio++ Development Team, (January 12, 2011)
-
-This software is a computer program whose purpose is to provide utilitary
-classes. This file belongs to the Bio++ Project.
-
-This software is governed by the CeCILL license under French law and
-abiding by the rules of distribution of free software. You can use,
-modify and/ or redistribute the software under the terms of the CeCILL
-license as circulated by CEA, CNRS and INRIA at the following URL
-"http://www.cecill.info".
-
-As a counterpart to the access to the source code and rights to copy,
-modify and redistribute granted by the license, users are provided only
-with a limited warranty and the software's author, the holder of the
-economic rights, and the successive licensors have only limited
-liability.
-
-In this respect, the user's attention is drawn to the risks associated
-with loading, using, modifying and/or developing or reproducing the
-software by the user in light of its specific status of free software,
-that may mean that it is complicated to manipulate, and that also
-therefore means that it is reserved for developers and experienced
-professionals having in-depth computer knowledge. Users are therefore
-encouraged to load and test the software's suitability as regards their
-requirements in conditions enabling the security of their systems and/or
-data to be ensured and, more generally, to use and operate it in the
-same conditions as regards security.
-
-The fact that you are presently reading this means that you have had
-knowledge of the CeCILL license and that you accept its terms.
-*/
-
-#include "BasicTNode.h"
-
-using namespace bpp;
-
-#include <cstddef>
-
-using namespace std;
-
-BasicTNode::~BasicTNode() {
- if (father_) {
- father_->removeSon(this);
- }
- for (size_t i = 0 ; i < sons_.size() ; i++) {
- sons_[i]->removeFather();
- }
-}
-
-BasicTNode::BasicTNode(const BasicTNode& node):
- sons_(node.sons_),
- father_(node.father_)
-{};
-
-BasicTNode& BasicTNode::operator=(const BasicTNode& node) {
- sons_ = node.sons_;
- father_ = node.father_;
- return * this;
-}
-
-// Neighbors
-
-const BasicTNode* BasicTNode::getNeighbor(int pos) const {
- if (pos < 0 || pos > static_cast<int>(sons_.size())) {
- throw IndexOutOfBoundsException("BasicTNode::getNeighbor() pos is out of bounds", static_cast<size_t>(pos), 0, sons_.size());
- }
- if (pos == 0)
- return father_;
- else
- return sons_[static_cast<size_t>(pos - 1)];
-}
-
-BasicTNode* BasicTNode::getNeighbor(int pos) {
- if (pos < 0 || pos > static_cast<int>(sons_.size())) {
- throw IndexOutOfBoundsException("BasicTNode::getNeighbor() pos is out of bounds", static_cast<size_t>(pos), 0, sons_.size());
- }
- if (pos == 0)
- return father_;
- else
- return sons_[static_cast<size_t>(pos - 1)];
-}
-
-const BasicTNode* BasicTNode::operator[](int i) const {
- if (i < 0) {
- return father_;
- } else {
- return sons_[static_cast<size_t>(i)];
- }
-}
-
-BasicTNode* BasicTNode::operator[](int i) {
- if (i < 0) {
- return father_;
- } else {
- return sons_[static_cast<size_t>(i)];
- }
-}
-
-// Fathers
-
-const BasicTNode* BasicTNode::getFather(int pos) const {
- if (pos != 0) {
- throw IndexOutOfBoundsException("BasicTNode::getFather() pos must be 0 for TNode", static_cast<size_t>(pos), 0, 0);
- }
- return getFather();
-}
-
-BasicTNode* BasicTNode::getFather(int pos) {
- if (pos != 0) {
- throw IndexOutOfBoundsException("BasicTNode::getFather() pos must be 0 for TNode", static_cast<size_t>(pos), 0, 0);
- }
- return getFather();
-}
-
-const BasicTNode* BasicTNode::getFather() const {
- return father_;
-}
-
-BasicTNode* BasicTNode::getFather() {
- return father_;
-}
-
-bool BasicTNode::isFather(const BasicTNode* node) const {
- if (father_ == node)
- return true;
- return false;
-}
-
-void BasicTNode::addFather(BasicTNode* node) {
- if (!node)
- throw NullPointerException("BasicTNode::addFather() Empty node given as input");
- if (father_)
- throw Exception("BasicTNode::addFather() This node already has a father.");
- if (!isFather(node))
- father_ = node;
- if (!node->isSon(this))
- node->addSon(this);
-}
-
-BasicTNode* BasicTNode::removeFather() {
- if (hasFathers()) {
- BasicTNode* father = father_;
- father_ = 0;
- father->removeSon(this);
- return father;
- }
- return 0;
-}
-
-// Sons
-
-const BasicTNode* BasicTNode::getSon(int pos) const {
- if (pos < 0 || pos > static_cast<int>(sons_.size()) - 1) {
- throw IndexOutOfBoundsException("BasicTNode::getSon() pos out of range", static_cast<size_t>(pos), 0, sons_.size() - 1);
- }
- return sons_[static_cast<size_t>(pos)];
-}
-
-BasicTNode* BasicTNode::getSon(int pos) {
- if (pos < 0 || pos > static_cast<int>(sons_.size()) - 1) {
- throw IndexOutOfBoundsException("BasicTNode::getSon() pos out of range", static_cast<size_t>(pos), 0, sons_.size() - 1);
- }
- return sons_[static_cast<size_t>(pos)];
-}
-
-bool BasicTNode::isSon(const BasicTNode* node) const {
- for (size_t i = 0 ; i < sons_.size() ; i++) {
- if (sons_[i] == node)
- return true;
- }
- return false;
-}
-
-void BasicTNode::addSon(BasicTNode* node) {
- if (!node)
- throw NullPointerException("BasicTNode::addSon() Empty node given as input.");
- if (!isSon(node))
- sons_.push_back(node);
- if (!node->isFather(this))
- node->addFather(this);
-}
-
-void BasicTNode::removeSon(BasicTNode* node) {
- if (!node)
- throw NullPointerException("BasicTNode::removeSon() Empty node given as input.");
- for (size_t i = 0 ; i < sons_.size() ; i++) {
- if (sons_[i] == node) {
- sons_.erase(sons_.begin() + static_cast<ptrdiff_t>(i));
- node->removeFather();
- }
- }
-}
-
-BasicTNode* BasicTNode::removeSon(int pos) {
- if (pos < 0 || pos > static_cast<int>(sons_.size() - 1))
- throw IndexOutOfBoundsException("BasicTNode::removeSon() pos out of bound", static_cast<size_t>(pos), 0, sons_.size() - 1);
- BasicTNode* node = sons_[static_cast<size_t>(pos)];
- sons_.erase(sons_.begin() + pos);
- node->removeFather();
- return node;
-}
diff --git a/src/Bpp/Graph/BasicTNode.h b/src/Bpp/Graph/BasicTNode.h
deleted file mode 100644
index 585bddf..0000000
--- a/src/Bpp/Graph/BasicTNode.h
+++ /dev/null
@@ -1,160 +0,0 @@
-//
-// File: BasicTNode.h
-// Author: Sylvain Gaillard
-// Created: 13/01/2011 16:39:23
-//
-
-/*
-Copyright or © or Copr. CNRS, (January 12, 2011)
-
-This software is a computer program whose purpose is to provide utilitary
-classes. This file belongs to the Bio++ Project.
-
-This software is governed by the CeCILL license under French law and
-abiding by the rules of distribution of free software. You can use,
-modify and/ or redistribute the software under the terms of the CeCILL
-license as circulated by CEA, CNRS and INRIA at the following URL
-"http://www.cecill.info".
-
-As a counterpart to the access to the source code and rights to copy,
-modify and redistribute granted by the license, users are provided only
-with a limited warranty and the software's author, the holder of the
-economic rights, and the successive licensors have only limited
-liability.
-
-In this respect, the user's attention is drawn to the risks associated
-with loading, using, modifying and/or developing or reproducing the
-software by the user in light of its specific status of free software,
-that may mean that it is complicated to manipulate, and that also
-therefore means that it is reserved for developers and experienced
-professionals having in-depth computer knowledge. Users are therefore
-encouraged to load and test the software's suitability as regards their
-requirements in conditions enabling the security of their systems and/or
-data to be ensured and, more generally, to use and operate it in the
-same conditions as regards security.
-
-The fact that you are presently reading this means that you have had
-knowledge of the CeCILL license and that you accept its terms.
-*/
-
-#ifndef _BPP_GRAPH_BASICTNODE_H_
-#define _BPP_GRAPH_BASICTNODE_H_
-
-#include "TNode.h"
-#include "../Exceptions.h"
-
-namespace bpp {
- /**
- * @brief Simple implementation of TNode
- *
- * Contains only methods for node manipulation.
- *
- * @author Sylvain Gaillard
- */
- class BasicTNode: public TNode {
- private:
- std::vector< BasicTNode * > sons_;
- BasicTNode * father_;
-
- public:
- /**
- * @brief Simple constructor.
- */
- BasicTNode(): sons_(), father_(0) {};
-
- /**
- * @brief Destructor.
- *
- * When destroyed, the node remove himself as son of its father and as
- * father of its sons.
- */
- virtual ~BasicTNode();
-
- /**
- * @brief Copy constructor.
- */
- BasicTNode(const BasicTNode& node);
-
- /**
- * @brief Assignation operator.
- */
- BasicTNode& operator=(const BasicTNode& node);
-
- BasicTNode* clone() const {
- return new BasicTNode(* this);
- }
-
- // Neighbors
-
- const BasicTNode* getNeighbor(int pos) const;
- BasicTNode* getNeighbor(int pos);
-
- int degree() const { return sons_.size() - 1 + father_ ? 1 : 0; }
-
- const BasicTNode* operator[](int i) const;
- BasicTNode* operator[](int i);
-
- // Fathers
-
- /**
- * @brief Tell if the node has a father.
- */
- bool hasFather() const { return father_ ? true : false; }
- bool hasFathers() const { return father_ ? true : false; }
- int getNumberOfFathers() const { return father_ ? 1 : 0; }
-
- const BasicTNode* getFather(int pos) const;
- BasicTNode* getFather(int pos);
- const BasicTNode* getFather() const;
- BasicTNode* getFather();
-
- /**
- * @brief Tell if the node is a father of this node.
- */
- virtual bool isFather(const BasicTNode* node) const;
-
- /**
- * @brief Add a father to this node.
- */
- virtual void addFather(BasicTNode* node);
-
- /**
- * @brief Remove the father of this node.
- *
- * @return A pointer to the removed father node.
- */
- virtual BasicTNode* removeFather();
-
- // Sons
-
- bool hasSons() const { return !sons_.empty(); }
- int getNumberOfSons() const { return static_cast<int>(sons_.size()); }
- const BasicTNode* getSon(int pos) const;
- BasicTNode* getSon(int pos);
-
- /**
- * @brief Tell if a node is son of this node.
- */
- virtual bool isSon(const BasicTNode* node) const;
-
- /**
- * @brief Add a son to this node.
- */
- virtual void addSon(BasicTNode* node);
-
- /**
- * @brief Remove a son of this node.
- */
- virtual void removeSon(BasicTNode* son);
-
- /**
- * @brief Remove a son of this node.
- *
- * @return A pointer to the removed son node or a Null pointer if son is
- * not found.
- */
- virtual BasicTNode* removeSon(int pos);
- };
-}
-
-#endif //_BPP_GRAPH_BASICTNODE_H_
diff --git a/src/Bpp/Graph/DAGraph.h b/src/Bpp/Graph/DAGraph.h
new file mode 100644
index 0000000..fe5ae8f
--- /dev/null
+++ b/src/Bpp/Graph/DAGraph.h
@@ -0,0 +1,174 @@
+//
+// File DAGraph.h
+// Created by: Laurent Guéguen
+// Last modification : lundi 19 décembre 2016, à 22h 46
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _DA_GRAPH_H_
+#define _DA_GRAPH_H_
+
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <ostream>
+
+
+#include "Graph.h"
+
+#include "../Exceptions.h"
+#include "../Numeric/VectorTools.h"
+
+namespace bpp
+{
+class DAGraph :
+ public virtual Graph
+{
+public:
+ /**
+ * Is the graph a directed acyclic?
+ * @return true if valid DAG
+ */
+ virtual bool isValid() const = 0;
+
+ /**
+ * Is the DAG rooted?
+ *
+ * @return true if rooted, ie has only one node with no father.
+ */
+
+ virtual bool isRooted() const = 0;
+
+ /**
+ * Check if node has a father
+ */
+
+ virtual bool hasFather(Graph::NodeId node) const = 0;
+
+ /**
+ * Get the fathers node of a node
+ */
+
+ virtual std::vector<Graph::NodeId> getFathers(Graph::NodeId node) const = 0;
+
+ /**
+ * @brief Get the number of fathers nodes
+ */
+
+ virtual size_t getNumberOfFathers(Graph::NodeId node) const = 0;
+
+ /**
+ * Add a father to a node
+ */
+
+ virtual void addFather(Graph::NodeId node, Graph::NodeId father) = 0;
+
+ virtual void addFather(Graph::NodeId node, Graph::NodeId father, Graph::EdgeId edgeId) = 0;
+
+ /**
+ * Remove one father
+ */
+
+ virtual void removeFather(Graph::NodeId node, Graph::NodeId father) = 0;
+
+ /**
+ * Remove all the fathers
+ */
+
+ virtual std::vector<Graph::NodeId> removeFathers(Graph::NodeId node) = 0;
+
+ /**
+ * Get the leaves under a node
+ * @param node the starting node
+ * @return a vector containing the leaves
+ */
+
+ virtual std::vector<Graph::NodeId> getLeavesUnderNode(Graph::NodeId node) const = 0;
+
+ /**
+ * Get the sons node of a node
+ */
+
+ virtual std::vector<Graph::NodeId> getSons(Graph::NodeId node) const = 0;
+
+ /**
+ * @brief Get the number of sons node
+ */
+
+ virtual size_t getNumberOfSons(Graph::NodeId node) const = 0;
+
+ /**
+ * Add a son to a node
+ */
+
+ void addSon(Graph::NodeId node, Graph::NodeId sonNode);
+
+ void addSon(Graph::NodeId node, Graph::NodeId sonNode, Graph::EdgeId edge);
+
+ /**
+ * Remove all the sons
+ */
+
+ virtual std::vector<Graph::NodeId> removeSons(Graph::NodeId node) = 0;
+
+ /**
+ * Remove one son
+ */
+
+ virtual void removeSon(Graph::NodeId node, Graph::NodeId son) = 0;
+
+ /**
+ * Re-root the DA with the new root
+ */
+
+ virtual void rootAt(Graph::NodeId newRoot) = 0;
+
+ /**
+ * Get all the nodes below a node
+ */
+
+ virtual std::vector<Graph::NodeId> getBelowNodes(Graph::NodeId localRoot) const = 0;
+
+ /**
+ * Get all the branches below a node
+ */
+
+ virtual std::vector<Graph::EdgeId> getBelowEdges(Graph::NodeId localRoot) const = 0;
+};
+}
+
+
+#endif
diff --git a/src/Bpp/Graph/DAGraphImpl.h b/src/Bpp/Graph/DAGraphImpl.h
new file mode 100644
index 0000000..7f5bc2d
--- /dev/null
+++ b/src/Bpp/Graph/DAGraphImpl.h
@@ -0,0 +1,525 @@
+//
+// File DAGraphImpl.h
+// Created by: Laurent Guéguen
+// Last modification : vendredi 4 novembre 2016, à 10h 21
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _DA_GRAPH_IMPL_H_
+#define _DA_GRAPH_IMPL_H_
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <ostream>
+
+
+#include "DAGraph.h"
+#include "GlobalGraph.h"
+
+#include "../Exceptions.h"
+#include "../Numeric/VectorTools.h"
+
+namespace bpp
+{
+template<class GraphImpl>
+class DAGraphImpl :
+ public virtual DAGraph,
+ public GraphImpl
+{
+protected:
+ /**
+ * Is the graph a DAG? Set to false when structure is modified, true after validation.
+ */
+
+ mutable bool isValid_;
+
+ /**
+ * Is the graph rooted? Set to false when structure is modified,
+ * true after validation.
+ */
+
+ mutable bool isRooted_;
+
+ // unvalidate the DAG
+ virtual void topologyHasChanged_() const;
+
+ // will throw an exception if the DA is not valid
+ void mustBeValid_() const;
+
+ // will throw an exception if the DA is not rooted, ie as more
+ // than one node with no father.
+
+ void mustBeRooted_() const;
+
+ // test the validity of the DAG
+ bool validate_() const;
+
+ /**
+ * Reorient at mimina all the edges starting from a node: the
+ * father nodes become sons, and so on.
+ *
+ * The Graph must already be rooted
+ */
+
+ void propagateDirection_(Graph::NodeId node);
+
+ /**
+ * Reorient all the graph so that localRoot is ahead the other
+ * sons, with the exception of the nodes already met
+ *
+ */
+
+ void orientGraphFrom_(std::set<Graph::NodeId>& metNodes, Graph::NodeId localRoot);
+
+public:
+ /**
+ * bool is only for inheritance from observers, useless.
+ *
+ */
+
+ DAGraphImpl(bool b = true);
+
+ /**
+ * Is the graph a DAG?
+ * @return true if valid DAG
+ */
+ bool isValid() const;
+
+ /**
+ * Is the DAG rooted?
+ *
+ * @return true if rooted, ie has only one node with no father.
+ */
+
+ bool isRooted() const;
+
+ /**
+ * Says if a node is a leaf (ie has at most one neighbor).
+ */
+
+ bool isLeaf(Graph::NodeId node) const;
+
+ /**
+ * Check if node has a father
+ */
+
+ bool hasFather(Graph::NodeId node) const;
+
+ /**
+ * Get the father nodes of a node
+ * @return the father node
+ */
+
+ std::vector<Graph::NodeId> getFathers(Graph::NodeId nodeid) const;
+
+ /**
+ * @brief Get the number of fathers nodes
+ */
+
+ size_t getNumberOfFathers(Graph::NodeId node) const;
+
+ /**
+ * Add a father to a node
+ */
+
+ void addFather(Graph::NodeId node, Graph::NodeId father);
+
+ void addFather(Graph::NodeId node, Graph::NodeId father, Graph::EdgeId edgeId);
+
+ /**
+ * Remove one father
+ */
+
+ void removeFather(Graph::NodeId node, Graph::NodeId father);
+
+ /**
+ * Remove all the fathers
+ */
+
+ std::vector<Graph::NodeId> removeFathers(Graph::NodeId node);
+
+ /**
+ * Get the leaves under a node
+ * @param node the starting node
+ * @return a vector containing the leaves
+ */
+
+ std::vector<Graph::NodeId> getLeavesUnderNode(Graph::NodeId node) const;
+
+ /**
+ * Get the sons node of a node
+ */
+
+ std::vector<Graph::NodeId> getSons(Graph::NodeId node) const;
+
+ /**
+ * @brief Get the number of sons node
+ */
+
+ size_t getNumberOfSons(Graph::NodeId node) const;
+
+ /**
+ * Add a son to a node
+ */
+
+ void addSon(Graph::NodeId node, Graph::NodeId sonNode);
+
+ void addSon(Graph::NodeId node, Graph::NodeId sonNode, Graph::EdgeId edge);
+
+ /**
+ * Remove all the sons
+ */
+
+ std::vector<Graph::NodeId> removeSons(Graph::NodeId node);
+
+ /**
+ * Remove one son
+ */
+
+ void removeSon(Graph::NodeId node, Graph::NodeId son);
+
+ /**
+ * Re-root the DA with the new root (and make the graph a DA if it is not)
+ */
+
+ void rootAt(Graph::NodeId newRoot);
+
+ /**
+ * Get all the nodes below a node
+ */
+
+ std::vector<Graph::NodeId> getBelowNodes(Graph::NodeId localRoot) const;
+
+ /**
+ * Get all the branches below a node
+ */
+
+ std::vector<Graph::EdgeId> getBelowEdges(Graph::NodeId localRoot) const;
+
+ // recursive function for getSubtreeNodes
+ void fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const;
+
+ // recursive function for getSubtreeEdges
+ void fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const;
+
+ // recursive function for getLeavesUnderNode
+ void fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const;
+};
+
+
+/******************/
+
+typedef DAGraphImpl<GlobalGraph> DAGlobalGraph;
+
+/*****************/
+
+
+template<class GraphImpl>
+DAGraphImpl<GraphImpl>::DAGraphImpl(bool b) :
+ GraphImpl(true),
+ isValid_(false),
+ isRooted_(false)
+{}
+
+
+template<class GraphImpl>
+bool DAGraphImpl<GraphImpl>::isValid() const
+{
+ return isValid_ || validate_();
+}
+
+
+template<class GraphImpl>
+bool DAGraphImpl<GraphImpl>::isRooted() const
+{
+ if (isRooted_)
+ return true;
+
+ std::unique_ptr<Graph::NodeIterator> allIt = allNodesIterator();
+ bool seen = false;
+
+ for ( ; !allIt->end(); allIt->next())
+ {
+ if (getNumberOfFathers(**allIt) == 0)
+ {
+ if (seen)
+ return false;
+ seen = true;
+ }
+ }
+
+ isRooted_ = seen;
+ return true;
+}
+
+template<class GraphImpl>
+bool DAGraphImpl<GraphImpl>::isLeaf(Graph::NodeId node) const
+{
+ return GraphImpl::isLeaf(node) == 0;
+}
+
+template<class GraphImpl>
+bool DAGraphImpl<GraphImpl>::hasFather(Graph::NodeId node) const
+{
+ return GraphImpl::getNumberOfIncomingNeighbors(node) >= 1;
+}
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getFathers(Graph::NodeId node) const
+{
+ return getIncomingNeighbors(node);
+}
+
+template<class GraphImpl>
+size_t DAGraphImpl<GraphImpl>::getNumberOfFathers(Graph::NodeId node) const
+{
+ return GraphImpl::getNumberOfIncomingNeighbors(node);
+}
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::addFather(Graph::NodeId node, Graph::NodeId fatherNode)
+{
+ GraphImpl::link(fatherNode, node);
+ topologyHasChanged_();
+ isRooted_ = false;
+}
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::addFather(Graph::NodeId node, Graph::NodeId fatherNode, Graph::EdgeId edge)
+{
+ GraphImpl::link(fatherNode, node, edge);
+ topologyHasChanged_();
+ isRooted_ = false;
+}
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::removeFathers(Graph::NodeId node)
+{
+ std::vector<Graph::NodeId> fathers = getFathers(node);
+ for (std::vector<Graph::NodeId>::iterator currFather = fathers.begin(); currFather != fathers.end(); currFather++)
+ {
+ removeFather(node, *currFather);
+ }
+ return fathers;
+}
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::removeFather(Graph::NodeId node, Graph::NodeId father)
+{
+ if (getNumberOfIncomingNeighbors(node) == 1)
+ isRooted_ = false;
+
+ GraphImpl::unlink(father, node);
+}
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getLeavesUnderNode(Graph::NodeId node) const
+{
+ std::vector<Graph::NodeId> foundLeaves;
+ fillListOfLeaves_(node, foundLeaves);
+
+ return foundLeaves;
+}
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const
+{
+ const std::vector<Graph::NodeId> sons = getSons(startingNode);
+ if (sons.size() > 1)
+ {
+ for (std::vector<Graph::NodeId>::const_iterator currNeighbor = sons.begin(); currNeighbor != sons.end(); currNeighbor++)
+ {
+ fillListOfLeaves_(*currNeighbor, foundLeaves);
+ }
+ }
+ else
+ {
+ foundLeaves.push_back(startingNode);
+ }
+}
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::mustBeRooted_() const
+{
+ if (!isRooted())
+ throw Exception("DAGraphImpl<GraphImpl>: The DAG must be rooted.");
+}
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::mustBeValid_() const
+{
+ if (!isValid())
+ throw Exception("DAGraphImpl<GraphImpl>: The DAG is not valid.");
+}
+
+
+template<class GraphImpl>
+bool DAGraphImpl<GraphImpl>::validate_() const
+{
+ isValid_ = GraphImpl::isDA();
+ return isValid_;
+}
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::topologyHasChanged_() const
+{
+ isValid_ = false;
+}
+
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getSons(Graph::NodeId node) const
+{
+ return GraphImpl::getOutgoingNeighbors(node);
+}
+
+template<class GraphImpl>
+size_t DAGraphImpl<GraphImpl>::getNumberOfSons(Graph::NodeId node) const
+{
+ return GraphImpl::getNumberOfOutgoingNeighbors(node);
+}
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::addSon(Graph::NodeId node, Graph::NodeId sonNode)
+{
+ GraphImpl::link(node, sonNode);
+ topologyHasChanged_();
+}
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::addSon(Graph::NodeId node, Graph::NodeId sonNode, Graph::EdgeId edge)
+{
+ GraphImpl::link(node, sonNode, edge);
+ topologyHasChanged_();
+}
+
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::removeSons(Graph::NodeId node)
+{
+ std::vector<Graph::NodeId> sons = getSons(node);
+ for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
+ {
+ removeSon(node, *currSon);
+ }
+ return sons;
+}
+
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::removeSon(Graph::NodeId node, Graph::NodeId son)
+{
+ GraphImpl::unlink(node, son);
+}
+
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::rootAt(Graph::NodeId newRoot)
+{
+ GraphImpl::setRoot(newRoot);
+
+ // change edge direction between the new node and the former fathers
+ if (isRooted() && isValid())
+ propagateDirection_(newRoot);
+ else
+ {
+ GraphImpl::orientate();
+ isRooted_ = true;
+ }
+}
+
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::propagateDirection_(Graph::NodeId node)
+{
+ std::vector<Graph::NodeId> vFat = getFathers(node);
+
+ for (size_t i = 0; i < vFat.size(); i++)
+ {
+ propagateDirection_(vFat[i]);
+ }
+
+ for (size_t i = 0; i < vFat.size(); i++)
+ {
+ GraphImpl::switchNodes(vFat[i], node);
+ }
+}
+
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getBelowNodes(Graph::NodeId localRoot) const
+{
+ mustBeValid_();
+ std::vector<Graph::EdgeId> metNodes;
+ fillSubtreeMetNodes_(metNodes, localRoot);
+ return metNodes;
+}
+
+template<class GraphImpl>
+std::vector<Graph::EdgeId> DAGraphImpl<GraphImpl>::getBelowEdges(Graph::NodeId localRoot) const
+{
+ mustBeValid_();
+ std::vector<Graph::EdgeId> metEdges;
+ fillSubtreeMetEdges_(metEdges, localRoot);
+ return metEdges;
+}
+
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const
+{
+ metNodes.push_back(localRoot);
+ std::vector<Graph::NodeId> sons = GraphImpl::getOutgoingNeighbors(localRoot);
+ for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
+ {
+ fillSubtreeMetNodes_(metNodes, *currSon);
+ }
+}
+
+template<class GraphImpl>
+void DAGraphImpl<GraphImpl>::fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const
+{
+ std::vector<Graph::EdgeId> edgesToSons = GraphImpl::getOutgoingEdges(localRoot);
+ for (std::vector<Graph::EdgeId>::iterator currEdgeToSon = edgesToSons.begin(); currEdgeToSon != edgesToSons.end(); currEdgeToSon++)
+ {
+ metEdges.push_back(*currEdgeToSon);
+ fillSubtreeMetEdges_(metEdges, GraphImpl::getBottom(*currEdgeToSon));
+ }
+}
+}
+
+
+#endif
diff --git a/src/Bpp/Graph/GlobalGraph.cpp b/src/Bpp/Graph/GlobalGraph.cpp
new file mode 100644
index 0000000..ab8f2df
--- /dev/null
+++ b/src/Bpp/Graph/GlobalGraph.cpp
@@ -0,0 +1,990 @@
+//
+// File GlobalGraph.cpp
+// Created by: Thomas Bigot
+// Last modification : vendredi 4 novembre 2016, à 10h 22
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+
+#include <string>
+#include <vector>
+#include <sstream>
+#include <algorithm>
+
+#include "GraphObserver.h"
+#include "GlobalGraph.h"
+#include "../Exceptions.h"
+
+using namespace bpp;
+using namespace std;
+
+GlobalGraph::GlobalGraph(bool directed_p) :
+ directed_(directed_p),
+ observers_(set<GraphObserver*>()),
+ highestNodeID_(0),
+ highestEdgeID_(0),
+ nodeStructure_(nodeStructureType()),
+ edgeStructure_(edgeStructureType()),
+ root_(0)
+{}
+
+
+GlobalGraph::GlobalGraph(const GlobalGraph& gg) :
+ directed_(gg.directed_),
+ observers_(gg.observers_),
+ highestNodeID_(gg.highestNodeID_),
+ highestEdgeID_(gg.highestEdgeID_),
+ nodeStructure_(gg.nodeStructure_),
+ edgeStructure_(gg.edgeStructure_),
+ root_(gg.root_)
+{}
+
+GlobalGraph& GlobalGraph::operator=(const GlobalGraph& gg)
+{
+ directed_ = gg.directed_;
+ observers_ = gg.observers_;
+ highestNodeID_ = gg.highestNodeID_;
+ highestEdgeID_ = gg.highestEdgeID_;
+ nodeStructure_ = gg.nodeStructure_;
+ edgeStructure_ = gg.edgeStructure_;
+ root_ = gg.root_;
+
+ return *this;
+}
+
+
+void GlobalGraph::nodeMustExist_(const GlobalGraph::Node& node, string name) const
+{
+ if (nodeStructure_.find(node) == nodeStructure_.end())
+ {
+ ostringstream errMessage;
+ errMessage << "This node must exist: " << node << " as " << name << ".";
+ throw (Exception(errMessage.str()));
+ }
+}
+
+void GlobalGraph::edgeMustExist_(const GlobalGraph::Edge& edge, string name) const
+{
+ if (edgeStructure_.find(edge) == edgeStructure_.end())
+ {
+ ostringstream errMessage;
+ errMessage << "This edge must exist: " << edge << " as " << name << ".";
+ throw (Exception(errMessage.str()));
+ }
+}
+
+
+GlobalGraph::Edge GlobalGraph::link(Graph::NodeId nodeA, Graph::NodeId nodeB)
+{
+ // which ID is available?
+ GlobalGraph::Edge edgeID = ++highestEdgeID_;
+
+ // writing the new relation to the structure
+ linkInNodeStructure_(nodeA, nodeB, edgeID);
+ if (!directed_)
+ {
+ linkInNodeStructure_(nodeB, nodeA, edgeID);
+ }
+ linkInEdgeStructure_(nodeA, nodeB, edgeID);
+ return edgeID;
+}
+
+void GlobalGraph::link(Graph::NodeId nodeA, Graph::NodeId nodeB, GlobalGraph::Edge edgeID)
+{
+ if (edgeStructure_.find(edgeID) != edgeStructure_.end())
+ throw Exception("GlobalGraph::link : already existing edgeId " + TextTools::toString(edgeID));
+
+ // writing the new relation to the structure
+ linkInNodeStructure_(nodeA, nodeB, edgeID);
+ if (!directed_)
+ {
+ linkInNodeStructure_(nodeB, nodeA, edgeID);
+ }
+ linkInEdgeStructure_(nodeA, nodeB, edgeID);
+}
+
+vector<GlobalGraph::Edge> GlobalGraph::unlink(Graph::NodeId nodeA, Graph::NodeId nodeB)
+{
+ // unlinking in the structure
+ vector<GlobalGraph::Edge> deletedEdges; // what edges ID are affected by this unlinking
+ deletedEdges.push_back(unlinkInNodeStructure_(nodeA, nodeB));
+
+ for (vector<GlobalGraph::Edge>::iterator currEdgeToDelete = deletedEdges.begin(); currEdgeToDelete != deletedEdges.end(); currEdgeToDelete++)
+ {
+ unlinkInEdgeStructure_(*currEdgeToDelete);
+ }
+
+ // telling the observers
+ notifyDeletedEdges(deletedEdges);
+
+ return deletedEdges;
+}
+
+void GlobalGraph::switchNodes(Graph::NodeId nodeA, Graph::NodeId nodeB)
+{
+ Graph::NodeId father, son;
+
+ nodeStructureType::iterator nodeARow = nodeStructure_.find(nodeA);
+ nodeStructureType::iterator nodeBRow = nodeStructure_.find(nodeB);
+ nodeStructureType::iterator nodeSonRow, nodeFatherRow;
+
+ // Forwards
+ map<GlobalGraph::Node, GlobalGraph::Edge>::iterator foundForwardRelation = nodeARow->second.first.find(nodeB);
+ if (foundForwardRelation == nodeARow->second.first.end())
+ {
+ foundForwardRelation = nodeBRow->second.first.find(nodeA);
+ if (foundForwardRelation == nodeBRow->second.first.end())
+ throw Exception("GlobalGraph::exchangeNodes : no edge between nodes " + TextTools::toString(nodeA) + " and " + TextTools::toString(nodeB));
+ father = nodeB;
+ son = nodeA;
+ nodeFatherRow = nodeBRow;
+ nodeSonRow = nodeARow;
+ }
+ else
+ {
+ father = nodeA;
+ son = nodeB;
+ nodeFatherRow = nodeARow;
+ nodeSonRow = nodeBRow;
+ }
+
+ // Edge
+ GlobalGraph::Edge& foundEdge = foundForwardRelation->second;
+
+ // Backwards
+ map<GlobalGraph::Node, GlobalGraph::Edge>::iterator foundBackwardsRelation = nodeSonRow->second.second.find(father);
+
+
+ // Exchange
+ nodeFatherRow->second.first.erase(foundForwardRelation);
+ nodeSonRow->second.second.erase(foundBackwardsRelation);
+
+
+ nodeSonRow->second.first[father] = foundEdge;
+
+ nodeFatherRow->second.second[son] = foundEdge;
+
+
+// std::map<GlobalGraph::Node, std::pair<std::map<GlobalGraph::Node, GlobalGraph::Edge>, std::map<GlobalGraph::Node, GlobalGraph::Edge> > >::iterator ita = nodeStructure_.find(nodeA);
+
+ edgeStructure_[foundEdge] = pair<Node, Node>(son, father);
+
+ this->topologyHasChanged_();
+}
+
+
+GlobalGraph::Node GlobalGraph::getHighestNodeID() const
+{
+ return highestNodeID_;
+}
+
+
+GlobalGraph::Edge GlobalGraph::getHighestEdgeID() const
+{
+ return highestEdgeID_;
+}
+
+void GlobalGraph::unlinkInEdgeStructure_(const GlobalGraph::Edge& edge)
+{
+ edgeStructureType::iterator foundEdge = edgeStructure_.find(edge);
+ if (foundEdge == edgeStructure_.end())
+ throw Exception("GlobalGraph::unlinkInEdgeStructure_ : no edge to erase " + TextTools::toString(edge));
+
+ edgeStructure_.erase(foundEdge);
+ this->topologyHasChanged_();
+}
+
+void GlobalGraph::linkInEdgeStructure_(const GlobalGraph::Node& nodeA, const GlobalGraph::Node& nodeB, const GlobalGraph::Edge& edge)
+{
+ edgeStructure_[edge] = pair<Node, Node>(nodeA, nodeB);
+ this->topologyHasChanged_();
+}
+
+
+unsigned int GlobalGraph::unlinkInNodeStructure_(const GlobalGraph::Node& nodeA, const GlobalGraph::Node& nodeB)
+{
+ // Forward
+ nodeStructureType::iterator nodeARow = nodeStructure_.find(nodeA);
+ map<GlobalGraph::Node, GlobalGraph::Edge>::iterator foundForwardRelation = nodeARow->second.first.find(nodeB);
+ if (foundForwardRelation == nodeARow->second.first.end())
+ throw Exception("GlobalGraph::unlinkInNodeStructure_ : no edge to erase " + TextTools::toString(nodeA) + "->" + TextTools::toString(nodeB));
+
+ GlobalGraph::Edge& foundEdge = foundForwardRelation->second;
+ nodeARow->second.first.erase(foundForwardRelation);
+
+ // Backwards
+ nodeStructureType::iterator nodeBRow = nodeStructure_.find(nodeB);
+ map<GlobalGraph::Node, GlobalGraph::Edge>::iterator foundBackwardsRelation = nodeBRow->second.second.find(nodeA);
+ if (foundBackwardsRelation == nodeBRow->second.first.end())
+ throw Exception("GlobalGraph::unlinkInNodeStructure_ : no edge to erase " + TextTools::toString(nodeB) + "<-" + TextTools::toString(nodeA));
+
+ nodeBRow->second.second.erase(foundBackwardsRelation);
+
+ this->topologyHasChanged_();
+ return foundEdge;
+}
+
+void GlobalGraph::linkInNodeStructure_(const GlobalGraph::Node& nodeA, const GlobalGraph::Node& nodeB, const GlobalGraph::Edge& edge)
+{
+ std::map<GlobalGraph::Node, std::pair<std::map<GlobalGraph::Node, GlobalGraph::Edge>, std::map<GlobalGraph::Node, GlobalGraph::Edge> > >::iterator ita = nodeStructure_.find(nodeA);
+
+ if (ita != nodeStructure_.end())
+ ita->second.first.insert( pair<GlobalGraph::Node, GlobalGraph::Edge>(nodeB, edge));
+
+ std::map<GlobalGraph::Node, std::pair<std::map<GlobalGraph::Node, GlobalGraph::Edge>, std::map<GlobalGraph::Node, GlobalGraph::Edge> > >::iterator itb = nodeStructure_.find(nodeB);
+
+ if (itb != nodeStructure_.end())
+ nodeStructure_.find(nodeB)->second.second.insert( pair<GlobalGraph::Node, GlobalGraph::Edge>(nodeA, edge));
+
+ this->topologyHasChanged_();
+}
+
+Graph::NodeId GlobalGraph::createNode()
+{
+ GlobalGraph::Node newNode = highestNodeID_++;
+ nodeStructure_[newNode] = std::pair<std::map<GlobalGraph::Node, GlobalGraph::Edge>, std::map<GlobalGraph::Node, GlobalGraph::Edge> >();
+ this->topologyHasChanged_();
+
+ return newNode;
+}
+
+Graph::NodeId GlobalGraph::createNodeFromNode(Graph::NodeId origin)
+{
+ Graph::NodeId newNode = createNode();
+ link(origin, newNode);
+ this->topologyHasChanged_();
+ return newNode;
+}
+
+Graph::NodeId GlobalGraph::createNodeOnEdge(Graph::EdgeId edge)
+{
+ // origin must be an existing edge
+ edgeMustExist_(edge, "");
+
+ Graph::NodeId newNode = createNode();
+
+ // determining the nodes on the border of the edge
+ pair<GlobalGraph::Node, GlobalGraph::Node> nodes = edgeStructure_[edge];
+ GlobalGraph::Node nodeA = nodes.first;
+ GlobalGraph::Node nodeB = nodes.second;
+
+ unlink(nodeA, nodeB);
+ link(nodeA, newNode);
+ link(newNode, nodeB);
+ this->topologyHasChanged_();
+ return newNode;
+}
+
+
+Graph::NodeId GlobalGraph::createNodeFromEdge(Graph::NodeId origin)
+{
+ // origin must be an existing edge
+ edgeMustExist_(origin, "origin edge");
+
+ // splitting the edge
+ Graph::NodeId anchor = createNodeOnEdge(origin);
+
+ Graph::NodeId newNode = createNodeFromNode(anchor);
+ this->topologyHasChanged_();
+ return newNode;
+}
+
+/*********************************************/
+
+void GlobalGraph::registerObserver(GraphObserver* observer)
+{
+ if (!observers_.insert(observer).second)
+ throw (Exception("This GraphObserver was already an observer of this Graph"));
+ ;
+}
+
+void GlobalGraph::unregisterObserver(GraphObserver* observer)
+{
+ if (!observers_.erase(observer))
+ throw (Exception("This GraphObserver was not an observer of this Graph"));
+}
+
+
+/**********************************************/
+
+std::vector< GlobalGraph::Node > GlobalGraph::getNeighbors_(const GlobalGraph::Node& node, bool outgoing) const
+{
+ nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
+ if (foundNode == nodeStructure_.end())
+ throw (Exception("The requested node is not in the structure."));
+ const std::map<GlobalGraph::Node, GlobalGraph::Edge>& forOrBack = (outgoing ? foundNode->second.first : foundNode->second.second);
+ vector<GlobalGraph::Node> result;
+ for (map<GlobalGraph::Node, GlobalGraph::Edge>::const_iterator currNeighbor = forOrBack.begin(); currNeighbor != forOrBack.end(); currNeighbor++)
+ {
+ result.push_back(currNeighbor->first);
+ }
+
+ return result;
+}
+
+std::vector< GlobalGraph::Edge > GlobalGraph::getEdges_(const GlobalGraph::Node& node, bool outgoing) const
+{
+ nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
+ if (foundNode == nodeStructure_.end())
+ throw (Exception("The requested node is not in the structure."));
+ const std::map<GlobalGraph::Node, GlobalGraph::Edge>& forOrBack = (outgoing ? foundNode->second.first : foundNode->second.second);
+ vector<GlobalGraph::Edge> result;
+ for (map<GlobalGraph::Node, GlobalGraph::Edge>::const_iterator currNeighbor = forOrBack.begin(); currNeighbor != forOrBack.end(); currNeighbor++)
+ {
+ result.push_back(currNeighbor->second);
+ }
+
+ return result;
+}
+
+vector< Graph::NodeId > GlobalGraph::getIncomingNeighbors(Graph::NodeId node) const
+{
+ return getNeighbors_(node, false);
+}
+
+vector< Graph::EdgeId > GlobalGraph::getIncomingEdges(const Graph::NodeId node) const
+{
+ return getEdges_(node, false);
+}
+
+vector< Graph::NodeId > GlobalGraph::getOutgoingNeighbors(const Graph::NodeId node) const
+{
+ return getNeighbors_(node, true);
+}
+
+vector< Graph::EdgeId > GlobalGraph::getOutgoingEdges(const Graph::NodeId node) const
+{
+ return getEdges_(node, true);
+}
+
+std::unique_ptr<Graph::NodeIterator> GlobalGraph::allNodesIterator()
+{
+ return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::ALLGRAPHITER, false>(*this));
+}
+
+std::unique_ptr<Graph::NodeIterator> GlobalGraph::allNodesIterator() const
+{
+ return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::ALLGRAPHITER, true>(*this));
+}
+
+
+std::unique_ptr<Graph::NodeIterator> GlobalGraph::outgoingNeighborNodesIterator(Graph::NodeId node)
+{
+ return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::OUTGOINGNEIGHBORITER, false>(*this, node));
+}
+
+
+std::unique_ptr<Graph::NodeIterator> GlobalGraph::incomingNeighborNodesIterator(Graph::NodeId node)
+{
+ return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::INCOMINGNEIGHBORITER, false>(*this, node));
+}
+
+std::unique_ptr<Graph::NodeIterator> GlobalGraph::outgoingNeighborNodesIterator(Graph::NodeId node) const
+{
+ return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::OUTGOINGNEIGHBORITER, true>(*this, node));
+}
+
+
+std::unique_ptr<Graph::NodeIterator> GlobalGraph::incomingNeighborNodesIterator(Graph::NodeId node) const
+{
+ return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::INCOMINGNEIGHBORITER, true>(*this, node));
+}
+
+
+size_t GlobalGraph::getNumberOfNodes() const
+{
+ return nodeStructure_.size();
+}
+
+
+size_t GlobalGraph::getNumberOfEdges() const
+{
+ return edgeStructure_.size();
+}
+
+
+size_t GlobalGraph::getDegree(const Graph::NodeId node) const
+{
+ nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
+ if (foundNode == nodeStructure_.end())
+ throw Exception("GlobalGraph::getDegree : Node " + TextTools::toString(node) + " does not exist.");
+
+ return isDirected() ? foundNode->second.first.size() + foundNode->second.second.size() : foundNode->second.first.size();
+}
+
+
+bool GlobalGraph::isLeaf(const Graph::NodeId node) const
+{
+ nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
+ if (foundNode == nodeStructure_.end())
+ throw Exception("GlobalGraph::isLeaf : Node " + TextTools::toString(node) + " does not exist.");
+
+ return (!isDirected() && (foundNode->second.first.size() <= 1))
+ || (isDirected() && (
+ (foundNode->second.first.size() + foundNode->second.second.size() <= 1)
+ || (foundNode->second.first.size() == 1 && foundNode->second.second.size() == 1 && foundNode->second.first.begin()->first == foundNode->second.second.begin()->first)));
+}
+
+
+size_t GlobalGraph::getNumberOfNeighbors(const Graph::NodeId node) const
+{
+ nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
+ if (foundNode == nodeStructure_.end())
+ throw (Exception("The requested node is not in the structure."));
+
+ if (isDirected())
+ return foundNode->second.first.size() + foundNode->second.second.size();
+ else
+ return foundNode->second.first.size();
+}
+
+size_t GlobalGraph::getNumberOfOutgoingNeighbors(const Graph::NodeId node) const
+{
+ nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
+ if (foundNode == nodeStructure_.end())
+ throw (Exception("The requested node is not in the structure."));
+ return foundNode->second.first.size();
+}
+
+size_t GlobalGraph::getNumberOfIncomingNeighbors(const Graph::NodeId node) const
+{
+ nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
+ if (foundNode == nodeStructure_.end())
+ throw (Exception("The requested node is not in the structure."));
+ return foundNode->second.second.size();
+}
+
+vector< Graph::NodeId > GlobalGraph::getNeighbors(const Graph::NodeId node) const
+{
+ vector<Graph::NodeId> result;
+ vector<Graph::NodeId> neighborsToInsert;
+ neighborsToInsert = getNeighbors_(node, false);
+ result.insert(result.end(), neighborsToInsert.begin(), neighborsToInsert.end());
+ neighborsToInsert = getNeighbors_(node, true);
+ result.insert(result.end(), neighborsToInsert.begin(), neighborsToInsert.end());
+ return result;
+}
+
+std::pair<Graph::NodeId, Graph::NodeId> GlobalGraph::getNodes(Graph::EdgeId edge) const
+{
+ edgeMustExist_(edge);
+ edgeStructureType::const_iterator found = edgeStructure_.find(edge);
+ // TODO Except if not found
+ return found->second;
+}
+
+Graph::NodeId GlobalGraph::getTop(Graph::EdgeId edge) const
+{
+ return std::get<0>(getNodes(edge));
+}
+
+Graph::NodeId GlobalGraph::getBottom(Graph::EdgeId edge) const
+{
+ return std::get<1>(getNodes(edge));
+}
+
+void GlobalGraph::deleteNode(Graph::NodeId node)
+{
+ // checking the node
+ nodeMustExist_(node, "node to delete");
+ isolate_(node);
+
+ nodeStructureType::iterator found = nodeStructure_.find(node);
+ if (found == nodeStructure_.end())
+ throw Exception("GlobalGraph::deleteNode : no node to erase " + TextTools::toString(node));
+
+ nodeStructure_.erase(found);
+
+ this->topologyHasChanged_();
+}
+
+void GlobalGraph::isolate_(GlobalGraph::Node& node)
+{
+ vector<Graph::NodeId> oneighbors = getOutgoingNeighbors(node);
+ for (vector<Graph::NodeId>::iterator currNeighbor = oneighbors.begin(); currNeighbor != oneighbors.end(); currNeighbor++)
+ {
+ unlink(node, *currNeighbor);
+ }
+
+ vector<Graph::NodeId> ineighbors = getIncomingNeighbors(node);
+ for (vector<Graph::NodeId>::iterator currNeighbor = ineighbors.begin(); currNeighbor != ineighbors.end(); currNeighbor++)
+ {
+ unlink(*currNeighbor, node);
+ }
+}
+
+vector<Graph::EdgeId> GlobalGraph::getAllEdges() const
+{
+ vector<Graph::EdgeId> listOfEdges;
+ for (edgeStructureType::const_iterator it = edgeStructure_.begin(); it != edgeStructure_.end(); it++)
+ {
+ listOfEdges.push_back(it->first);
+ }
+
+ return listOfEdges;
+}
+
+Graph::EdgeId GlobalGraph::getAnyEdge(Graph::NodeId nodeA, Graph::NodeId nodeB) const
+{
+ try
+ {
+ // trying in the given order A->B
+ return getEdge(nodeA, nodeB);
+ }
+ catch (Exception e)
+ {
+ // didn’t work, hence trying in the opposite order B->A
+ return getEdge(nodeB, nodeA);
+ }
+}
+
+vector<Graph::NodeId> GlobalGraph::getAllLeaves() const
+{
+ vector<Graph::NodeId> listOfLeaves;
+ for (nodeStructureType::const_iterator it = nodeStructure_.begin(); it != nodeStructure_.end(); it++)
+ {
+ if (this->isLeaf(it->first))
+ listOfLeaves.push_back(it->first);
+ }
+
+ return listOfLeaves;
+}
+
+set<Graph::NodeId> GlobalGraph::getSetOfAllLeaves() const
+{
+ set<Graph::NodeId> listOfLeaves;
+ for (nodeStructureType::const_iterator it = nodeStructure_.begin(); it != nodeStructure_.end(); it++)
+ {
+ if (this->isLeaf(it->first))
+ listOfLeaves.insert(it->first);
+ }
+
+ return listOfLeaves;
+}
+
+vector<Graph::NodeId> GlobalGraph::getAllNodes() const
+{
+ vector<Graph::NodeId> listOfNodes;
+ for (nodeStructureType::const_iterator it = nodeStructure_.begin(); it != nodeStructure_.end(); it++)
+ {
+ listOfNodes.push_back(it->first);
+ }
+
+ return listOfNodes;
+}
+
+vector<Graph::NodeId> GlobalGraph::getAllInnerNodes() const
+{
+ vector<Graph::NodeId> listOfInNodes;
+ for (nodeStructureType::const_iterator it = nodeStructure_.begin(); it != nodeStructure_.end(); it++)
+ {
+ if (this->getDegree(it->first) >= 2)
+ listOfInNodes.push_back(it->first);
+ }
+
+ return listOfInNodes;
+}
+
+
+void GlobalGraph::fillListOfLeaves_(const GlobalGraph::Node& startingNode, vector<GlobalGraph::Node>& foundLeaves, const GlobalGraph::Node& originNode, unsigned int maxRecursions) const
+{
+ const vector<Graph::NodeId> neighbors = getNeighbors(startingNode);
+ if (neighbors.size() > 1)
+ {
+ if (maxRecursions > 0)
+ for (vector<Node>::const_iterator currNeighbor = neighbors.begin(); currNeighbor != neighbors.end(); currNeighbor++)
+ {
+ if (*currNeighbor != originNode)
+ fillListOfLeaves_(*currNeighbor, foundLeaves, startingNode, maxRecursions - 1);
+ }
+ }
+ else
+ {
+ foundLeaves.push_back(startingNode);
+ }
+}
+
+
+std::vector<Graph::NodeId> GlobalGraph::getLeavesFromNode(const Graph::NodeId node, unsigned int maxDepth) const
+{
+ vector<Graph::NodeId> listOfLeaves;
+ fillListOfLeaves_(node, listOfLeaves, node, maxDepth);
+ return listOfLeaves;
+}
+
+void GlobalGraph::nodeToDot_(const GlobalGraph::Node& node, ostream& out, std::set<std::pair<Node, Node> >& alreadyFigured) const
+{
+ bool theEnd = true;
+ const std::map<Node, Edge>& children = nodeStructure_.at(node).first;
+ for (map<Node, Edge>::const_iterator currChild = children.begin(); currChild != children.end(); currChild++)
+ {
+ if (alreadyFigured.find(pair<Node, Node>(node, currChild->first)) != alreadyFigured.end() || (!directed_ && alreadyFigured.find(pair<Node, Node>(currChild->first, node)) != alreadyFigured.end()))
+ continue;
+ alreadyFigured.insert(pair<Node, Node>(node, currChild->first));
+ theEnd = false;
+ out << node << (directed_ ? " -> " : " -- ");
+ nodeToDot_(currChild->first, out, alreadyFigured);
+ }
+
+ const std::map<Node, Edge>& fathers = nodeStructure_.at(node).second;
+ for (map<Node, Edge>::const_iterator currFath = fathers.begin(); currFath != fathers.end(); currFath++)
+ {
+ if (alreadyFigured.find(pair<Node, Node>(currFath->first, node)) != alreadyFigured.end() || (!directed_ && alreadyFigured.find(pair<Node, Node>(node, currFath->first)) != alreadyFigured.end()))
+ continue;
+ alreadyFigured.insert(pair<Node, Node>(currFath->first, node));
+ theEnd = false;
+ out << node << (directed_ ? " <- " : " -- ");
+ nodeToDot_(currFath->first, out, alreadyFigured);
+ }
+ if (theEnd)
+ out << node << ";\n ";
+}
+
+bool GlobalGraph::isTree() const
+{
+ set<GlobalGraph::Node> metNodes;
+ bool nodesAreMetOnlyOnce = nodesAreMetOnlyOnce_(root_, metNodes, root_);
+
+ if (!nodesAreMetOnlyOnce)
+ return false;
+ // now they have only been met at most once, they have to be met at least once
+ bool noNodeMissing = true;
+ for (nodeStructureType::const_iterator currNode = nodeStructure_.begin(); noNodeMissing && currNode != nodeStructure_.end(); currNode++)
+ {
+ noNodeMissing = (metNodes.find(currNode->first) != metNodes.end());
+ }
+ return noNodeMissing;
+}
+
+
+bool GlobalGraph::nodesAreMetOnlyOnce_(const GlobalGraph::Node& node, set< GlobalGraph::Node >& metNodes, const GlobalGraph::Node& originNode) const
+{
+ // insert().second <=> not yet in the set
+ bool neverMetANodeMoreThanOnce = metNodes.insert(node).second;
+ vector<Graph::NodeId> neighbors = getOutgoingNeighbors(node);
+ for (vector<Graph::NodeId>::iterator currNeighbor = neighbors.begin(); neverMetANodeMoreThanOnce && currNeighbor != neighbors.end(); currNeighbor++)
+ {
+ if (*currNeighbor == originNode)
+ continue;
+ neverMetANodeMoreThanOnce = nodesAreMetOnlyOnce_(*currNeighbor, metNodes, node);
+ }
+ return neverMetANodeMoreThanOnce;
+}
+
+bool GlobalGraph::isDA() const
+{
+ GlobalGraph gg(*this);
+
+ // Algo: remove recursively all nodes with no sons from graph
+
+ std::vector<Graph::NodeId> vL;
+
+ std::unique_ptr<Graph::NodeIterator> it = gg.allNodesIterator();
+ for ( ; !it->end(); it->next())
+ {
+ if (gg.getNumberOfOutgoingNeighbors(**it) == 0)
+ vL.push_back(**it);
+ }
+
+ while (vL.size() != 0)
+ {
+ for (std::vector<Graph::NodeId>::iterator it2(vL.begin()); it2 != vL.end(); it2++)
+ {
+ gg.deleteNode(*it2);
+ }
+
+ if (gg.getNumberOfNodes() == 0)
+ return true;
+
+ vL.clear();
+
+ it = gg.allNodesIterator();
+ for ( ; !it->end(); it->next())
+ {
+ if (gg.getNumberOfOutgoingNeighbors(**it) == 0)
+ vL.push_back(**it);
+ }
+ }
+
+ return false;
+}
+
+
+void GlobalGraph::orientate()
+{
+ if (!isDirected())
+ makeDirected();
+
+ GlobalGraph gg(*this);
+
+ // Algo: remove recursively all nodes from graph, starting with
+ // root_
+
+ Graph::NodeId node = root_;
+ std::set<Graph::NodeId> nextNodes;
+ nextNodes.insert(node);
+
+ while (gg.getNumberOfNodes() != 0)
+ {
+ // look for the next node to be treated
+ Graph::NodeId nbgg = 0;
+
+ // first node with one neighbor (ie no choice on orientation)
+
+ std::set<Graph::NodeId>::iterator it = nextNodes.begin();
+ for ( ; it != nextNodes.end(); it++)
+ {
+ if (gg.getNumberOfNeighbors(*it) <= 1)
+ break;
+ }
+
+ // if none, look for node wih minimum number of fathers
+ if (it == nextNodes.end())
+ {
+ size_t nbF = numeric_limits<size_t>::infinity();
+ it = nextNodes.begin();
+
+ for ( ; it != nextNodes.end(); it++)
+ {
+ size_t nbFi = gg.getNumberOfIncomingNeighbors(*it);
+ if (nbF == 0)
+ {
+ nbgg = *it;
+ break;
+ }
+ else
+ {
+ if (nbFi < nbF)
+ {
+ nbgg = *it;
+ nbF = nbFi;
+ }
+ }
+ }
+ }
+ else
+ nbgg = *it;
+
+ // next orient edges from this node and catch neighbors
+ std::vector<Graph::NodeId> vL = gg.getIncomingNeighbors(nbgg);
+ for (std::vector<Graph::NodeId>::iterator it2(vL.begin()); it2 != vL.end(); it2++)
+ {
+ switchNodes(nbgg, *it2);
+
+ nextNodes.insert(*it2);
+ }
+
+ vL = gg.getOutgoingNeighbors(nbgg);
+ for (std::vector<Graph::NodeId>::iterator it2(vL.begin()); it2 != vL.end(); it2++)
+ {
+ nextNodes.insert(*it2);
+ }
+
+ gg.deleteNode(nbgg);
+ nextNodes.erase(nbgg);
+ }
+}
+
+void GlobalGraph::setRoot(Graph::NodeId newRoot)
+{
+ nodeMustExist_(newRoot, "new root");
+ root_ = newRoot;
+}
+
+Graph::NodeId GlobalGraph::getRoot() const
+{
+ return root_;
+}
+
+
+bool GlobalGraph::isDirected() const
+{
+ return directed_;
+}
+
+void GlobalGraph::makeDirected()
+{
+ if (directed_)
+ return;
+ // save and clean the undirectedStructure
+ nodeStructureType undirectedStructure = nodeStructure_;
+ for (nodeStructureType::iterator it = nodeStructure_.begin(); it != nodeStructure_.end(); it++)
+ {
+ it->second = std::pair<std::map<Node, Edge>, std::map<Node, Edge> >();
+ }
+ // copy each relation once, without the reciprocal link
+ // (first met, first kept)
+ // eg: A - B in undirected is represented as A->B and B->A
+ // in directed, becomes A->B only
+ std::set<pair<Node, Node> > alreadyConvertedRelations;
+ for (nodeStructureType::iterator currNodeRow = undirectedStructure.begin(); currNodeRow != undirectedStructure.end(); currNodeRow++)
+ {
+ Node nodeA = currNodeRow->first;
+
+ for (map<Node, Edge>::iterator currRelation = currNodeRow->second.first.begin(); currRelation != currNodeRow->second.first.end(); currRelation++)
+ {
+ Node nodeB = currRelation->first;
+ Edge edge = currRelation->second;
+ if (alreadyConvertedRelations.insert(pair<Node, Node>(min(nodeA, nodeB), max(nodeA, nodeB))).second)
+ linkInNodeStructure_(nodeA, nodeB, edge);
+ }
+ }
+ directed_ = true;
+ this->topologyHasChanged_();
+}
+
+void GlobalGraph::makeUndirected()
+{
+ if (!directed_)
+ return;
+ if (containsReciprocalRelations())
+ throw Exception("Cannot make an undirected graph from a directed one containing reciprocal relations.");
+ // save and clean the undirectedStructure
+ nodeStructureType directedStructure = nodeStructure_;
+ for (nodeStructureType::iterator it = nodeStructure_.begin(); it != nodeStructure_.end(); it++)
+ {
+ it->second = std::pair<std::map<Node, Edge>, std::map<Node, Edge> >();
+ }
+ // copy each relation twice, making the reciprocal link
+ // eg: A - B in directed is represented as A->B
+ // in undirected, becomes A->B and B->A
+ for (nodeStructureType::iterator currNodeRow = directedStructure.begin(); currNodeRow != directedStructure.end(); currNodeRow++)
+ {
+ Node nodeA = currNodeRow->first;
+ for (map<Node, Edge>::iterator currRelation = currNodeRow->second.first.begin(); currRelation != currNodeRow->second.first.end(); currRelation++)
+ {
+ Node nodeB = currRelation->first;
+ Edge edge = currRelation->second;
+ linkInNodeStructure_(nodeA, nodeB, edge);
+ linkInNodeStructure_(nodeB, nodeA, edge);
+ }
+ }
+ directed_ = false;
+ this->topologyHasChanged_();
+}
+
+bool GlobalGraph::containsReciprocalRelations() const
+{
+ if (!directed_)
+ throw Exception("Cannot state reciprocal link in an undirected graph.");
+ std::set<pair<Node, Node> > alreadyMetRelations;
+ for (nodeStructureType::const_iterator currNodeRow = nodeStructure_.begin(); currNodeRow != nodeStructure_.end(); currNodeRow++)
+ {
+ Node nodeA = currNodeRow->first;
+ for (map<Node, Edge>::const_iterator currRelation = currNodeRow->second.first.begin(); currRelation != currNodeRow->second.first.end(); currRelation++)
+ {
+ Node nodeB = currRelation->first;
+ if (!alreadyMetRelations.insert(pair<Node, Node>(min(nodeA, nodeB), max(nodeA, nodeB))).second)
+ return true;
+ }
+ }
+ return false;
+}
+
+std::unique_ptr<Graph::EdgeIterator> GlobalGraph::allEdgesIterator()
+{
+ return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::ALLGRAPHITER, false>(*this));
+}
+
+std::unique_ptr<Graph::EdgeIterator> GlobalGraph::outgoingEdgesIterator(Graph::NodeId node)
+{
+ return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::OUTGOINGNEIGHBORITER, false>(*this, node));
+}
+
+std::unique_ptr<Graph::EdgeIterator> GlobalGraph::incomingEdgesIterator(Graph::NodeId node)
+{
+ return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::INCOMINGNEIGHBORITER, false>(*this, node));
+}
+
+std::unique_ptr<Graph::EdgeIterator> GlobalGraph::allEdgesIterator() const
+{
+ return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::ALLGRAPHITER, true>(*this));
+}
+
+std::unique_ptr<Graph::EdgeIterator> GlobalGraph::outgoingEdgesIterator(Graph::NodeId node) const
+{
+ return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::OUTGOINGNEIGHBORITER, true>(*this, node));
+}
+
+std::unique_ptr<Graph::EdgeIterator> GlobalGraph::incomingEdgesIterator(Graph::NodeId node) const
+{
+ return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::INCOMINGNEIGHBORITER, true>(*this, node));
+}
+
+Graph::EdgeId GlobalGraph::getEdge(Graph::NodeId nodeA, Graph::NodeId nodeB) const
+{
+ nodeStructureType::const_iterator firstNodeFound = nodeStructure_.find(nodeA);
+ if (firstNodeFound == nodeStructure_.end())
+ throw (Exception("The fist node was not the origin of an edge."));
+ map<Node, Edge>::const_iterator secondNodeFound = firstNodeFound->second.first.find(nodeB);
+ if (secondNodeFound == firstNodeFound->second.first.end())
+ throw (Exception("The second node was not in a relation with the first one."));
+ return secondNodeFound->second;
+}
+
+vector<Graph::EdgeId> GlobalGraph::getEdges(Graph::NodeId node) const
+{
+ vector<Graph::EdgeId> result;
+ vector<Graph::EdgeId> edgesToInsert;
+ edgesToInsert = getEdges_(node, false);
+ result.insert(result.end(), edgesToInsert.begin(), edgesToInsert.end());
+ edgesToInsert = getEdges_(node, true);
+ result.insert(result.end(), edgesToInsert.begin(), edgesToInsert.end());
+ return result;
+}
+
+void GlobalGraph::outputToDot(ostream& out, const std::string& name) const
+{
+ out << (directed_ ? "digraph" : "graph") << " " << name << " {\n ";
+ set<pair<Node, Node> > alreadyFigured;
+ nodeToDot_(root_, out, alreadyFigured);
+ out << "\r}" << endl;
+}
+
+void GlobalGraph::notifyDeletedEdges(const vector<Graph::EdgeId>& edgesToDelete) const
+{
+ for (set<GraphObserver*>::iterator currObserver = observers_.begin(); currObserver != observers_.end(); currObserver++)
+ {
+ (*currObserver)->deletedEdgesUpdate(edgesToDelete);
+ }
+}
+
+void GlobalGraph::notifyDeletedNodes(const vector<Graph::NodeId>& nodesToDelete) const
+{
+ for (set<GraphObserver*>::iterator currObserver = observers_.begin(); currObserver != observers_.end(); currObserver++)
+ {
+ (*currObserver)->deletedNodesUpdate(nodesToDelete);
+ }
+}
diff --git a/src/Bpp/Graph/GlobalGraph.h b/src/Bpp/Graph/GlobalGraph.h
new file mode 100644
index 0000000..98c7189
--- /dev/null
+++ b/src/Bpp/Graph/GlobalGraph.h
@@ -0,0 +1,956 @@
+//
+// File GlobalGraph.h
+// Created by: Thomas Bigot
+// Laurent Gueguen
+// Last modification : vendredi 4 novembre 2016, à 10h 19
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _GLOBAL_GRAPH_H_
+#define _GLOBAL_GRAPH_H_
+
+#include "../Clonable.h"
+
+#include <set>
+#include <map>
+#include <string>
+#include "Graph.h"
+
+namespace bpp
+{
+class GlobalGraph :
+ public virtual Graph,
+ public virtual Clonable
+{
+public:
+ typedef Graph::NodeId Node;
+ typedef Graph::EdgeId Edge;
+
+ /**
+ * The node structure type
+ * Node -> ("toNodes" [DestNode,Edge],"fromNodes" [DestNode,Edge])
+ * directed example: (N1)-E1->(N2)-E2->(N3) is coded as
+ * N1 -> ((N2:E1),())
+ * N2 -> ((N3:E3),(N1:E1))
+ * N3 -> ((),(N2:E2))
+ * undirected example: (N1)-E1-(N2)-E2->(N3) is coded as
+ * N1 -> ((N2:E1),(N2:E1))
+ * N2 -> ((N1:E1, N3:E3),(N1:E1, N3:E3))
+ * N3 -> ((N2:E2),(N2:E2))
+ */
+ typedef std::map<Node, std::pair<std::map<Node, Edge>, std::map<Node, Edge> > > nodeStructureType;
+
+ /**
+ * The edge structure type
+ * directed example: N1--E1-->N2 is coded as E1 -> (N1,N2)
+ * undirected example: N1--E1--N2 is coded as E1 -> (N1,N2)
+ */
+ typedef std::map<Edge, std::pair<Node, Node> > edgeStructureType;
+
+private:
+ /**
+ * is the graph directed
+ */
+ bool directed_;
+
+ /**
+ * List of all the subscribers.
+ */
+ std::set<GraphObserver*> observers_;
+
+ /**
+ * Highest used available ID for a Node.
+ */
+ Node highestNodeID_;
+ /**
+ * Highest used available ID for an Edge.
+ */
+ Edge highestEdgeID_;
+
+ /**
+ * Nodes and their relations.
+ * see nodeStructureType documentation
+ */
+
+ nodeStructureType nodeStructure_;
+
+ /**
+ * Edges and their relations in the forward direction..
+ * see edgeStructureType documentation
+ */
+ edgeStructureType edgeStructure_;
+
+ /**
+ * Usualy the first node of a graph. Used for algorithmic purposes.
+ */
+ Node root_;
+
+ /**
+ * Some types of Graphs need to know if they have been modified
+ * But for a Graph, it does nothing.
+ */
+ virtual void topologyHasChanged_() const
+ {
+ // do nothing: a Graph does not care to be modified
+ }
+
+ /**
+ * Tell all the observers to get the last updates.
+ * Calls the method update of all the subscribers.
+ */
+ void notify_();
+
+ /**
+ * Creates a link between two existing nodes. If directed graph: nodeA -> nodeB.
+ * Private version of link, does not check for the reciprocity.
+ * Mainly called by link().
+ * @param nodeA source node
+ * @param nodeB target node
+ * @param edge the ID of the relation
+ */
+ void linkInNodeStructure_(const Node& nodeA, const Node& nodeB, const Edge& edge);
+
+ /**
+ * Creates a link between two existing nodes in the edge structure.
+ * If directed graph: nodeA -> nodeB.
+ * Mainly called by link().
+ * @param nodeA source node (or first node if undirected)
+ * @param nodeB target node (or second node if undirected)
+ * @param edge the ID of the relation
+ */
+ void linkInEdgeStructure_(const Node& nodeA, const Node& nodeB, const Edge& edge);
+
+
+ /**
+ * Erase a link between two existing nodes. If directed graph: nodeA -> nodeB.
+ * Private version of unLink, does not check for the reciprocity.
+ * Mainly called by unLink().
+ * @param nodeA source node
+ * @param nodeB target node
+ * @return the ID of the erased relation
+ */
+
+ Edge unlinkInNodeStructure_(const Node& nodeA, const Node& nodeB);
+
+ /**
+ * Erase a link between two existing nodes in the Edge structure.
+ * Mainly called by unLink().
+ * @param edge the edge to unregister
+ */
+
+ void unlinkInEdgeStructure_(const Edge& edge);
+
+protected:
+ /**
+ * get the Highest Node ID (for vector sizing)
+ */
+ Node getHighestNodeID() const;
+
+ /**
+ * get the Highest Node ID (for vector sizing)
+ */
+ Edge getHighestEdgeID() const;
+
+
+ /**
+ * Check that a node exists. If not, throw an exception.
+ * @param node node that has to be checked
+ * @param name common name to give to the user in case of failure (eg: "first node")
+ */
+ void nodeMustExist_(const Node& node, std::string name = "") const;
+
+ /**
+ * Check that a edge exists. If not, throw an exception.
+ * @param edge edge that has to be checked
+ * @param name common name to give to the user in case of failure (eg: "first node")
+ */
+ void edgeMustExist_(const Edge& edge, std::string name = "") const;
+
+private:
+ /**
+ * Private version of getIncomingNeighbors or getOutgoingNeighbors.
+ * Common code of these function shared here.
+ * @param node node to in or outgoing neighbors
+ * @param outgoing boolean: if true, outgoing; else incoming
+ */
+ std::vector<Node> getNeighbors_(const Node& node, bool outgoing = true) const;
+
+ /**
+ * Private version of getIncomingEdges or getOutgoingEdges.
+ * Common code of these function shared here.
+ * @param node node to in or outgoing edges
+ * @param outgoing boolean: if true, outgoing; else incoming
+ */
+ std::vector<Edge> getEdges_(const Node& node, bool outgoing = true) const;
+
+ /**
+ * Separate a node from all its neighbors.
+ * @param node node to isolate
+ */
+
+ void isolate_(Node& node);
+
+ /**
+ * Get leaves from a starting node, filling a vector (private version).
+ * @param startingNode root node
+ * @param foundLeaves a vector containing all the found leaves
+ * @param originNode the node where we come from, not to explore
+ * @param maxRecursions maximum number of recursion steps
+ */
+
+ void fillListOfLeaves_(const Node& startingNode, std::vector<Node>& foundLeaves, const Node& originNode, unsigned int maxRecursions) const;
+
+ /**
+ * Check that nodes are only met once to define if the graph is cyclic.
+ * @param node the node to explore
+ * @param metNodes a set containing all the nodes we met
+ * @param originNode the node where we come from, not to explore
+ */
+ bool nodesAreMetOnlyOnce_(const Node& node, std::set<Node>& metNodes, const Node& originNode) const;
+
+ /**
+ * output a node to DOT format (recursive)
+ */
+
+ void nodeToDot_(const Node& node, std::ostream& out, std::set<std::pair<Node, Node> >& alreadyFigured) const;
+
+public:
+ /** @name General Management
+ * Misc & constructors
+ */
+ // /@{
+
+
+ /**
+ * Constructor
+ * @param directed true if the graph is directed.
+ */
+ GlobalGraph(bool directed = false);
+
+ GlobalGraph(const GlobalGraph& gg);
+
+ GlobalGraph& operator=(const GlobalGraph& gg);
+
+ GlobalGraph* clone() const {return new GlobalGraph(*this); }
+
+ ~GlobalGraph() {}
+
+protected:
+ /**
+ * set the root node to an existing node. Will not affect the topology.
+ * @param newRoot the new root
+ */
+
+ void setRoot(Graph::NodeId newRoot);
+
+public:
+ /**
+ * get the root node
+ */
+
+ Graph::NodeId getRoot() const;
+
+ /**
+ * Make the graph directed
+ * - changes the property
+ * - de-duplicate the relations:
+ * eg: A - B in undirected is represented as A->B and B->A
+ * in directed, becomes A->B only
+ *
+ * Please note that the resulting directions are totaly arbritrary.
+ * One might consider to use the makeLocalRoot method.
+ */
+ void makeDirected();
+
+ /**
+ * Make the graph directed
+ * - changes the property
+ * - de-duplicate the relations:
+ * eg: A - B in directed is represented as A->B
+ * in undirected, becomes A->B and B->A
+ * If the directed graph already contains reciprocal relations,
+ * such as A->B and B->A, the method will throw an exception.
+ */
+ void makeUndirected();
+
+ // /@}
+
+
+ /** @name Relations management
+ * Modificating the structure of the graph.
+ */
+ // /@{
+
+ /**
+ * Creates an orphaned node.
+ * @return the new node
+ */
+
+ Graph::NodeId createNode();
+
+ /**
+ * Creates a node linked to an existing node.
+ * @param origin existing node. In a directed graph: origin -> newNode.
+ * @return the new node
+ */
+
+ Graph::NodeId createNodeFromNode(Graph::NodeId origin);
+
+ /**
+ * Creates new node on an existing Edge. A -> B will be A -> N -> B
+ * @param edge existing edge.
+ * @return the new node
+ */
+
+ Graph::NodeId createNodeOnEdge(Graph::EdgeId edge);
+
+ /**
+ * Creates a node linked to new node, splitting an edge.
+ * @param origin existing edge. In a directed graph: origin -> newNode.
+ * @return the new node
+ */
+
+ Graph::NodeId createNodeFromEdge(Graph::NodeId origin);
+
+protected:
+ /**
+ * Creates a link between two existing nodes. If directed graph: nodeA -> nodeB.
+ * @param nodeA source node (or first node if undirected)
+ * @param nodeB target node (or second node if undirected)
+ * @return the new edge
+ */
+
+ Graph::EdgeId link(Graph::NodeId nodeA, Graph::NodeId nodeB);
+
+ /**
+ * Sets a link between two existing nodes, using existing edge. If
+ * directed graph: nodeA -> nodeB.
+ * @param nodeA source node (or first node if undirected)
+ * @param nodeB target node (or second node if undirected)
+ * @param edgeID the used edge
+ */
+
+ void link(Graph::NodeId nodeA, Graph::NodeId nodeB, GlobalGraph::Edge edgeID);
+
+ /**
+ * Switch the edge between two existing nodes.
+ *
+ * @param nodeA source node (or first node if undirected)
+ * @param nodeB target node (or second node if undirected)
+ */
+
+ void switchNodes(Graph::NodeId nodeA, Graph::NodeId nodeB);
+
+
+ /**
+ * Remove all links between two existing nodes. If directed graph: nodeA -> nodeB.
+ * @param nodeA source node (or first node if undirected)
+ * @param nodeB target node (or second node if undirected)
+ * @return vector of deleted edges
+ */
+
+ std::vector<Graph::EdgeId> unlink(Graph::NodeId nodeA, Graph::NodeId nodeB);
+
+public:
+ /**
+ * Delete one node
+ * @param node node to be deleted
+ */
+
+ void deleteNode(Graph::NodeId node);
+
+ // /@}
+
+
+ /** @name Observers Management
+ * Managing communication with the observers: subscribe, unsubscribe.
+ */
+ // /@{
+
+ /**
+ * Attach a new observer to this Graph.
+ * As a subscriber, the observer will be warned of all the changes.
+ */
+ void registerObserver(GraphObserver* observer);
+ /**
+ * Detach an observer from this Graph.
+ * The observer will not be warned of changes anymore.
+ */
+ void unregisterObserver(GraphObserver* observer);
+ // /@}
+
+
+ /** @name Nodes Functions
+ * These methodes of the graph concern the node management.
+ */
+ // /@{
+
+ template<typename T, bool is_const>
+ friend class NodesIteratorClass;
+
+ template<typename T, bool is_const>
+ friend class EdgesIteratorClass;
+
+ /*
+ * @brief builds iterator on all Nodes of the graph
+ *
+ */
+
+ std::unique_ptr<Graph::NodeIterator> allNodesIterator();
+ std::unique_ptr<Graph::NodeIterator> allNodesIterator() const;
+
+
+ /*
+ * @brief builds iterator on the neighbor nodes of a Node
+ *
+ */
+
+ std::unique_ptr<Graph::NodeIterator> outgoingNeighborNodesIterator(NodeId node);
+ std::unique_ptr<Graph::NodeIterator> outgoingNeighborNodesIterator(NodeId node) const;
+
+ /*
+ * @brief builds iterator on the neighbor nodes of a Node
+ *
+ */
+
+ std::unique_ptr<Graph::NodeIterator> incomingNeighborNodesIterator(NodeId node);
+ std::unique_ptr<Graph::NodeIterator> incomingNeighborNodesIterator(NodeId node) const;
+
+ /**
+ * Get the number of nodes in the graph.
+ */
+
+ size_t getNumberOfNodes() const;
+
+ /**
+ * Get the number of edges in the graph.
+ */
+
+ size_t getNumberOfEdges() const;
+
+ /**
+ * Get the degree of a node (ie the number of neighbors) in the graph.
+ * @param node the node one wants to count its neighbors
+ * @return the number of neighbors
+ */
+
+ size_t getDegree(Graph::NodeId node) const;
+
+ /**
+ * Says if a node is a leaf (ie has at most one neighbor).
+ */
+
+ bool isLeaf(Graph::NodeId node) const;
+
+ /**
+ * Get the number of neighbors of a node in the graph.
+ * @param node the node one wants to count its neighbors
+ * @return the number of neighbors
+ */
+
+ size_t getNumberOfNeighbors(Graph::NodeId node) const;
+
+ /**
+ * Get the number of outgoing neighbors of a node (ie the number of sons) in the graph.
+ * @param node the node one wants to count its sons
+ * @return the number of outgoing neighbors
+ */
+
+ size_t getNumberOfOutgoingNeighbors(Graph::NodeId node) const;
+
+ /**
+ * Get the number of incoming neighbors of a node (ie the number of fathers) in the graph.
+ * @param node the node one wants to count its fathers
+ * @return the number of incoming neighbors
+ */
+
+ size_t getNumberOfIncomingNeighbors(Graph::NodeId node) const;
+
+ /**
+ * Get all the neighbors of a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the neighbors
+ */
+
+ std::vector<Graph::NodeId> getNeighbors(Graph::NodeId node) const;
+
+ /**
+ * In an directed graph, get all the neighbors which
+ * are leaving a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the outgoing neighbors
+ */
+ std::vector<Graph::NodeId> getOutgoingNeighbors(Graph::NodeId node) const;
+
+ /**
+ * In an directed graph, get all the neighbors which
+ * are coming to a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the incoming neighbors
+ */
+ std::vector<Graph::NodeId> getIncomingNeighbors(Graph::NodeId node) const;
+
+ /**
+ * Get the leaves of a graph, ie, nodes with only one neighbor,
+ * starting from a peculiar node.
+ * @param node the starting node
+ * @param maxDepth the maximum number of allowed depth.
+ * @return a vector containing the leaves
+ */
+ std::vector<Graph::NodeId> getLeavesFromNode(Graph::NodeId node, unsigned int maxDepth) const;
+
+ /**
+ * Get all leaves of a graph, ie, nodes with no son (or only one
+ * neighbor is not directet).
+ * @return a vector containing the leaves
+ */
+
+ std::vector<Graph::NodeId> getAllLeaves() const;
+ std::set<NodeId> getSetOfAllLeaves() const;
+
+ /**
+ * Get all the nodes.
+ * @return a vector containing the nodes
+ */
+
+ std::vector<Graph::NodeId> getAllNodes() const;
+
+ /**
+ * Get all the inner nodes, ie, nodes with degree > 1.
+ * @return a vector containing the inner nodes
+ */
+
+ std::vector<Graph::NodeId> getAllInnerNodes() const;
+
+ /**
+ * Get nodes located at the extremities of an edge
+ *
+ * @return a pair of the IDs of the Nodes at each extremity of the edge
+ * example : N1--E1-->N2; getNodes(E1) will return (N1,N2);
+ */
+ std::pair<Graph::NodeId, Graph::NodeId> getNodes(Graph::EdgeId edge) const;
+
+ /**
+ * Get node located at the top of an edge
+ *
+ * @return the Node at the top the edge
+ * example : N1--E1-->N2; getTop(E1) will return N1;
+ */
+
+ Graph::NodeId getTop(Graph::EdgeId edge) const;
+
+ /**
+ * Get node located at the bottom of an edge
+ *
+ * @return the Node at the bottom the edge
+ * example : N1--E1-->N2; getBottom(E1) will return N2;
+ */
+
+ Graph::NodeId getBottom(Graph::EdgeId edge) const;
+
+
+ // /@}
+
+ /** @name Topological Properties
+ * These methodes check some topological properties.
+ */
+ // /@{
+
+ /**
+ * Is the graph a tree?
+ * @return false if a node is met more than one time browsing the graph
+ */
+
+ bool isTree() const;
+
+ /**
+ * Is the graph directed acyclic?
+ * @return true if an edge is met more than one time browsing the graph
+ */
+
+ bool isDA() const;
+
+ /**
+ * Orientates the graph hanging from the root
+ */
+
+ void orientate();
+
+ /**
+ * Is the graph directed?
+ * @return true the type of the graph is directed
+ */
+ bool isDirected() const;
+
+
+ /**
+ * Does the graph contain reciprocal relations such as A->B and B->A?
+ * @return true if one of them is seen in the structure
+ */
+ bool containsReciprocalRelations() const;
+
+
+ // /@}
+
+ /*
+ * @brief builds iterator on all Nodes of the graph
+ *
+ */
+
+ std::unique_ptr<EdgeIterator> allEdgesIterator();
+ std::unique_ptr<EdgeIterator> allEdgesIterator() const;
+
+ /*
+ * @brief builds iterator on the outgoing neighbor nodes of a Node
+ *
+ */
+
+ std::unique_ptr<EdgeIterator> outgoingEdgesIterator(NodeId node);
+ std::unique_ptr<EdgeIterator> outgoingEdgesIterator(NodeId node) const;
+
+ /*
+ * @brief builds iterator on the incoming neighbor nodes of a Node
+ *
+ */
+
+ std::unique_ptr<EdgeIterator> incomingEdgesIterator(NodeId node);
+ std::unique_ptr<EdgeIterator> incomingEdgesIterator(NodeId node) const;
+
+ /**
+ * Get all the edges to/from a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the edges
+ */
+
+ std::vector<Graph::EdgeId> getEdges(Graph::NodeId node) const;
+
+ /**
+ * In an directed graph, get all the edges which
+ * are leaving a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the outgoing edges
+ */
+ std::vector<Graph::EdgeId> getOutgoingEdges(Graph::NodeId node) const;
+
+ /**
+ * In an directed graph, get all the edges which
+ * are coming to a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the incoming edges
+ */
+ std::vector<Graph::EdgeId> getIncomingEdges(Graph::NodeId node) const;
+
+ /**
+ * Returns the Edge between two nodes
+ * @param nodeA if directed, origin node
+ * @param nodeB if directed, destination node
+ * @return the edge between these two nodes
+ */
+
+ Graph::EdgeId getEdge(Graph::NodeId nodeA, Graph::NodeId nodeB) const;
+
+ /**
+ * Returns the Edge between two nodes, trying both directions
+ * @param nodeA any node implied in the relation
+ * @param nodeB any other node implied in the relation
+ * @return the edge between these two nodes
+ */
+
+ Graph::EdgeId getAnyEdge(Graph::NodeId nodeA, Graph::NodeId nodeB) const;
+
+ /**
+ * Get all edges of a graph.
+ * @return a vector containing the edges
+ */
+
+ std::vector<Graph::EdgeId> getAllEdges() const;
+
+ // /@}
+
+
+ /** @name Updating the changes on the observers
+ * These methodes aim to trigger some changes to the observers
+ */
+ // /@{
+
+ /**
+ * Trigger E objects deleting on the observers
+ * @param edgesToDelete list of edges to delete
+ */
+
+ void notifyDeletedEdges(const std::vector<Graph::EdgeId>& edgesToDelete) const;
+
+ /**
+ * Trigger N objects deleting on the observers
+ * @param nodesToDelete list of edges to delete
+ */
+ void notifyDeletedNodes(const std::vector<Graph::NodeId>& nodesToDelete) const;
+
+
+ // /@}
+
+ /**
+ * Output the graph in DOT format
+ * @param out a ostream where the DOT format will be output
+ * @param name a string naming the graph
+ */
+
+ void outputToDot(std::ostream& out, const std::string& name) const;
+
+ template<class N, class E, class GraphImpl>
+ friend class AssociationGraphImplObserver;
+};
+
+
+/************************************************/
+/************************************************/
+/************************************************/
+/* ITERATORS */
+/************************************************/
+
+/************************************************/
+/* NODES ITERATORS */
+/************************************************/
+
+template<class T, bool is_const>
+class NodesIteratorClass :
+ virtual public Graph::NodeIterator
+{
+ ~NodesIteratorClass<T, is_const>(){}
+};
+
+
+template<bool is_const>
+class NodesIteratorClass<Graph::ALLGRAPHITER, is_const> :
+ virtual public Graph::NodeIterator
+{
+private:
+ typedef typename std::conditional<is_const,
+ GlobalGraph::nodeStructureType::const_iterator,
+ GlobalGraph::nodeStructureType::iterator >::type itType;
+
+ itType it_, begin_, end_;
+
+public:
+ template<bool B = is_const>
+ NodesIteratorClass<Graph::ALLGRAPHITER, is_const>(const GlobalGraph &gg, typename std::enable_if<B>::type * = 0) : it_(gg.nodeStructure_.begin()),
+ begin_(gg.nodeStructure_.begin()),
+ end_(gg.nodeStructure_.end()) {}
+
+ template<bool B = is_const>
+ NodesIteratorClass<Graph::ALLGRAPHITER, is_const>(GlobalGraph & gg, typename std::enable_if<!B>::type * = 0) : it_(gg.nodeStructure_.begin()),
+ begin_(gg.nodeStructure_.begin()),
+ end_(gg.nodeStructure_.end()) {}
+
+ ~NodesIteratorClass<Graph::ALLGRAPHITER, is_const>(){}
+
+ void next() { it_++; }
+ bool end() const { return it_ == end_; }
+ void start() { it_ = begin_; }
+
+ Graph::NodeId operator*() {return it_->first; }
+};
+
+
+/**
+ * @brief Abstract class for neighbor iterators
+ *
+ **/
+
+template<bool is_const>
+class NeighborIteratorClass
+{
+protected:
+ typedef typename std::conditional<is_const,
+ const std::map<GlobalGraph::Node, GlobalGraph::Edge>&,
+ std::map<GlobalGraph::Node, GlobalGraph::Edge>&>::type mapType;
+
+ mapType map_;
+
+ typedef typename std::conditional<is_const,
+ std::map<GlobalGraph::Node, GlobalGraph::Edge>::const_iterator,
+ std::map<GlobalGraph::Node, GlobalGraph::Edge>::iterator>::type itType;
+
+ itType it_, begin_, end_;
+
+public:
+ virtual ~NeighborIteratorClass<is_const>(){}
+
+ template<bool B = is_const>
+ NeighborIteratorClass<is_const>(const std::map<GlobalGraph::Node, GlobalGraph::Edge> &map, typename std::enable_if<B>::type * = 0) :
+ map_(map),
+ it_(map_.begin()),
+ begin_(map_.begin()),
+ end_(map_.end()) {}
+
+ template<bool B = is_const>
+ NeighborIteratorClass<is_const>(std::map<GlobalGraph::Node, GlobalGraph::Edge> &map, typename std::enable_if<!B>::type * = 0) :
+ map_(map),
+ it_(map_.begin()),
+ begin_(map_.begin()),
+ end_(map_.end()) {}
+
+ void next() { it_++; }
+ bool end() const { return it_ == end_; }
+ void start() { it_ = begin_; }
+};
+
+
+/**
+ * @brief
+ *
+ **/
+
+template<bool is_const>
+class NodesIteratorClass<Graph::OUTGOINGNEIGHBORITER, is_const> :
+ virtual public NeighborIteratorClass<is_const>,
+ virtual public Graph::NodeIterator
+{
+public:
+ NodesIteratorClass<Graph::OUTGOINGNEIGHBORITER, is_const>(const GlobalGraph &gg, GlobalGraph::NodeId node) : NeighborIteratorClass<is_const>(gg.nodeStructure_.find(node)->second.first) {}
+
+ NodesIteratorClass<Graph::OUTGOINGNEIGHBORITER, is_const>(GlobalGraph & gg, GlobalGraph::NodeId node) : NeighborIteratorClass<is_const>(gg.nodeStructure_.find(node)->second.first) {}
+
+ ~NodesIteratorClass<Graph::OUTGOINGNEIGHBORITER, is_const>(){}
+
+ void next() { NeighborIteratorClass<is_const>::next(); }
+ bool end() const { return NeighborIteratorClass<is_const>::end(); }
+ void start() { NeighborIteratorClass<is_const>::start(); }
+
+ Graph::NodeId operator*() {return NeighborIteratorClass<is_const>::it_->first; }
+};
+
+
+template<bool is_const>
+class NodesIteratorClass<Graph::INCOMINGNEIGHBORITER, is_const> :
+ virtual public NeighborIteratorClass<is_const>,
+ virtual public Graph::NodeIterator
+{
+public:
+ NodesIteratorClass<Graph::INCOMINGNEIGHBORITER, is_const>(const GlobalGraph &gg, GlobalGraph::NodeId node) : NeighborIteratorClass<is_const>(gg.nodeStructure_.find(node)->second.second) {}
+
+ NodesIteratorClass<Graph::INCOMINGNEIGHBORITER, is_const>(GlobalGraph & gg, GlobalGraph::NodeId node) : NeighborIteratorClass<is_const>(gg.nodeStructure_.find(node)->second.second) {}
+
+ ~NodesIteratorClass<Graph::INCOMINGNEIGHBORITER, is_const>(){}
+
+ void next() { NeighborIteratorClass<is_const>::next(); }
+ bool end() const { return NeighborIteratorClass<is_const>::end(); }
+ void start() { NeighborIteratorClass<is_const>::start(); }
+
+ Graph::NodeId operator*() {return NeighborIteratorClass<is_const>::it_->first; }
+};
+
+
+/************************************************/
+/* EDGES ITERATORS */
+/************************************************/
+
+template<class T, bool is_const>
+class EdgesIteratorClass :
+ virtual public Graph::EdgeIterator
+{};
+
+template<bool is_const>
+class EdgesIteratorClass<Graph::ALLGRAPHITER, is_const> :
+ virtual public Graph::EdgeIterator
+{
+private:
+ typedef typename std::conditional<is_const,
+ GlobalGraph::edgeStructureType::const_iterator,
+ GlobalGraph::edgeStructureType::iterator >::type itType;
+
+ itType it_, begin_, end_;
+
+public:
+ template<bool B = is_const>
+ EdgesIteratorClass<Graph::ALLGRAPHITER, is_const>(const GlobalGraph &gg, typename std::enable_if<B>::type * = 0) : it_(gg.edgeStructure_.begin()),
+ begin_(gg.edgeStructure_.begin()),
+ end_(gg.edgeStructure_.end()) {}
+
+ template<bool B = is_const>
+ EdgesIteratorClass<Graph::ALLGRAPHITER, is_const>(GlobalGraph & gg, typename std::enable_if<!B>::type * = 0) : it_(gg.edgeStructure_.begin()),
+ begin_(gg.edgeStructure_.begin()),
+ end_(gg.edgeStructure_.end()) {}
+
+ ~EdgesIteratorClass<Graph::ALLGRAPHITER, is_const>(){}
+
+ void next() { it_++; }
+ bool end() const { return it_ == end_; }
+ void start() { it_ = begin_; }
+
+ Graph::EdgeId operator*() {return it_->first; }
+};
+
+
+template<bool is_const>
+class EdgesIteratorClass<Graph::OUTGOINGNEIGHBORITER, is_const> :
+ public NeighborIteratorClass<is_const>,
+ public Graph::EdgeIterator
+{
+public:
+ EdgesIteratorClass<Graph::OUTGOINGNEIGHBORITER, is_const>(const GlobalGraph &gg, GlobalGraph::NodeId node) : NeighborIteratorClass<is_const>(gg.nodeStructure_.find(node)->second.first) {}
+
+ EdgesIteratorClass<Graph::OUTGOINGNEIGHBORITER, is_const>(GlobalGraph & gg, GlobalGraph::NodeId node) : NeighborIteratorClass<is_const>(gg.nodeStructure_.find(node)->second.first) {}
+
+ ~EdgesIteratorClass<Graph::OUTGOINGNEIGHBORITER, is_const>(){}
+
+ void next() { NeighborIteratorClass<is_const>::next(); }
+ bool end() const { return NeighborIteratorClass<is_const>::end(); }
+ void start() { NeighborIteratorClass<is_const>::start(); }
+
+ Graph::EdgeId operator*() {return NeighborIteratorClass<is_const>::it_->second; }
+};
+
+template<bool is_const>
+class EdgesIteratorClass<Graph::INCOMINGNEIGHBORITER, is_const> :
+ public NeighborIteratorClass<is_const>,
+ public Graph::EdgeIterator
+{
+public:
+ EdgesIteratorClass<Graph::INCOMINGNEIGHBORITER, is_const>(const GlobalGraph &gg, GlobalGraph::NodeId node) : NeighborIteratorClass<is_const>(gg.nodeStructure_.find(node)->second.second) {}
+
+ EdgesIteratorClass<Graph::INCOMINGNEIGHBORITER, is_const>(GlobalGraph & gg, GlobalGraph::NodeId node) : NeighborIteratorClass<is_const>(gg.nodeStructure_.find(node)->second.second) {}
+
+ ~EdgesIteratorClass<Graph::INCOMINGNEIGHBORITER, is_const>(){}
+
+ void next() { NeighborIteratorClass<is_const>::next(); }
+ bool end() const { return NeighborIteratorClass<is_const>::end(); }
+ void start() { NeighborIteratorClass<is_const>::start(); }
+
+ Graph::EdgeId operator*() {return NeighborIteratorClass<is_const>::it_->second; }
+};
+}
+
+#endif
diff --git a/src/Bpp/Graph/Graph.h b/src/Bpp/Graph/Graph.h
new file mode 100644
index 0000000..23301a6
--- /dev/null
+++ b/src/Bpp/Graph/Graph.h
@@ -0,0 +1,582 @@
+//
+// File Graph.h
+// Created by: Thomas Bigot
+// Last modification : vendredi 4 novembre 2016, à 10h 21
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _GRAPH_H_
+#define _GRAPH_H_
+
+#include <set>
+#include <map>
+#include <string>
+#include <vector>
+#include <utility>
+#include <iostream>
+#include <algorithm>
+#include <memory>
+
+
+// forward declaration to avoid circular dependancies.
+// since we do not need its size in this header file (only using pointers to it)
+namespace bpp
+{
+class GraphObserver;
+}
+
+namespace bpp
+{
+class Graph
+{
+public:
+ typedef unsigned int NodeId;
+ typedef unsigned int EdgeId;
+
+
+ virtual ~Graph(){}
+
+protected:
+ /**
+ * set the root node to an existing node. Will not affect the topology.
+ * @param newRoot the new root
+ */
+
+ virtual void setRoot(NodeId newRoot) = 0;
+
+public:
+ /**
+ * get the root node
+ */
+
+ virtual NodeId getRoot() const = 0;
+
+ /**
+ * Make the graph directed
+ * - changes the property
+ * - de-duplicate the relations:
+ * eg: A - B in undirected is represented as A->B and B->A
+ * in directed, becomes A->B only
+ *
+ * Please note that the resulting directions are totaly arbritrary.
+ * One might consider to use the makeLocalRoot method.
+ */
+
+ virtual void makeDirected() = 0;
+
+ /**
+ * Make the graph directed
+ * - changes the property
+ * - de-duplicate the relations:
+ * eg: A - B in directed is represented as A->B
+ * in undirected, becomes A->B and B->A
+ * If the directed graph already contains reciprocal relations,
+ * such as A->B and B->A, the method will throw an exception.
+ */
+
+ virtual void makeUndirected() = 0;
+
+ // /@}
+
+
+ /** @name Relations management
+ * Modificating the structure of the graph.
+ */
+ // /@{
+
+ /**
+ * Creates an orphaned node.
+ * @return the index of the new node
+ */
+
+ virtual NodeId createNode() = 0;
+
+ /**
+ * Creates a node linked to an existing node.
+ * @param origin existing node. In a directed graph: origin -> newNode.
+ * @return the index of the new node
+ */
+
+ virtual NodeId createNodeFromNode(NodeId origin) = 0;
+
+ /**
+ * Creates new node on an existing Edge. A -> B will be A -> N -> B
+ * @param edge existing edge.
+ * @return the index of the new node
+ */
+ virtual NodeId createNodeOnEdge(NodeId edge) = 0;
+
+
+ /**
+ * Creates a node linked to new node, splitting an edge.
+ * @param origin existing edge. In a directed graph: origin -> newNode.
+ * @return the index of the new node
+ */
+
+ virtual NodeId createNodeFromEdge(NodeId origin) = 0;
+
+protected:
+ /**
+ * Creates a link between two existing nodes. If directed graph: nodeA -> nodeB.
+ * @param nodeA source node (or first node if undirected)
+ * @param nodeB target node (or second node if undirected)
+ * @return the index of the new edge
+ */
+
+ virtual EdgeId link(NodeId nodeA, NodeId nodeB) = 0;
+
+ /**
+ * Sets a link between two existing nodes, using existing edge. If
+ * directed graph: nodeA -> nodeB.
+ * @param nodeA source node (or first node if undirected)
+ * @param nodeB target node (or second node if undirected)
+ * @param edgeID the used edge
+ */
+
+ virtual void link(Graph::NodeId nodeA, Graph::NodeId nodeB, Graph::EdgeId edgeID) = 0;
+
+ /**
+ * Remove all links between two existing nodes. If directed graph: nodeA -> nodeB.
+ * @param nodeA source node (or first node if undirected)
+ * @param nodeB target node (or second node if undirected)
+ * @return vector of IDs to de-assigned edges
+ */
+
+ virtual std::vector<EdgeId> unlink(NodeId nodeA, NodeId nodeB) = 0;
+
+public:
+ /**
+ * Delete one node
+ * @param node node to be deleted
+ */
+
+ virtual void deleteNode(NodeId node) = 0;
+
+ // /@}
+
+ /** @name Observers Management
+ * Managing communication with the observers: subscribe, unsubscribe.
+ */
+ // /@{
+
+ /**
+ * Attach a new observer to this Graph.
+ * As a subscriber, the observer will be warned of all the changes.
+ */
+
+ virtual void registerObserver(GraphObserver* observer) = 0;
+
+ /**
+ * Detach an observer from this Graph.
+ * The observer will not be warned of changes anymore.
+ */
+
+ virtual void unregisterObserver(GraphObserver* observer) = 0;
+
+// /@}
+
+ /** @name Nodes Functions
+ * These methodes of the graph concern the node management.
+ */
+ // /@{
+
+ /**
+ * @name Iterator interface on Nodes
+ *
+ */
+
+ class NodeIterator
+ {
+public:
+ virtual ~NodeIterator() {}
+
+ virtual void next() = 0;
+ virtual bool end() const = 0;
+ virtual void start() = 0;
+
+ virtual NodeId operator*() = 0;
+ };
+
+ /**
+ * @brief define categories of iterators
+ *
+ */
+
+ struct ALLGRAPHITER {};
+ struct OUTGOINGNEIGHBORITER {};
+ struct INCOMINGNEIGHBORITER {};
+
+ /*
+ * @brief builds iterator on all Nodes of the graph
+ *
+ */
+
+ virtual std::unique_ptr<NodeIterator> allNodesIterator() = 0;
+
+ virtual std::unique_ptr<NodeIterator> allNodesIterator() const = 0;
+
+ /*
+ * @brief builds iterator on the outgoing neighbor nodes of a Node
+ *
+ */
+
+ virtual std::unique_ptr<NodeIterator> outgoingNeighborNodesIterator(NodeId node) = 0;
+
+ /*
+ * @brief builds iterator on the incoming neighbor nodes of a Node
+ *
+ */
+
+ virtual std::unique_ptr<NodeIterator> incomingNeighborNodesIterator(NodeId node) = 0;
+
+
+ /**
+ * Get the number of nodes in the graph.
+ */
+
+ virtual size_t getNumberOfNodes() const = 0;
+
+ /**
+ * Get the number of edges in the graph.
+ */
+
+ virtual size_t getNumberOfEdges() const = 0;
+
+ /**
+ * Get the degree of a node (ie the number of neighbors) in the graph.
+ * @param node the node one wants to count its neighbors
+ * @return the number of neighbors
+ */
+
+ virtual size_t getDegree(NodeId node) const = 0;
+
+ /**
+ * Says if a node is a leaf (ie has at most one neighbor).
+ */
+
+ virtual bool isLeaf(NodeId node) const = 0;
+
+ /**
+ * Get the number of neighbors of a node in the graph.
+ * @param node the node one wants to count its sons
+ * @return the number of neighbors
+ */
+
+ virtual size_t getNumberOfNeighbors(NodeId node) const = 0;
+
+ /**
+ * Get the number of outgoing neighbors of a node (ie the number of sons) in the graph.
+ * @param node the node one wants to count its sons
+ * @return the number of outgoing neighbors
+ */
+
+ virtual size_t getNumberOfOutgoingNeighbors(NodeId node) const = 0;
+
+ /**
+ * Get the number of incoming neighbors of a node (ie the number of fathers) in the graph.
+ * @param node the node one wants to count its fathers
+ * @return the number of incoming neighbors
+ */
+
+ virtual size_t getNumberOfIncomingNeighbors(const NodeId node) const = 0;
+
+ /**
+ * Get all the neighbors of a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the ID of the neighbors
+ */
+
+ virtual std::vector<NodeId> getNeighbors(const NodeId node) const = 0;
+
+ /**
+ * In an directed graph, get all the neighbors which
+ * are leaving a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the ID of the outgoing neighbors
+ */
+
+ virtual std::vector<NodeId> getOutgoingNeighbors(const NodeId node) const = 0;
+
+ /**
+ * In an directed graph, get all the neighbors which
+ * are coming to a node in the graph.
+ * @param node the node one wants to get its neighbors
+ * @return a vector containing the incoming neighbors
+ */
+
+ virtual std::vector<NodeId> getIncomingNeighbors(NodeId node) const = 0;
+
+ /**
+ * Get the leaves of a graph, ie, nodes with only one neighbor,
+ * starting from a peculiar node.
+ * @param node the starting node
+ * @param maxDepth the maximum number of allowed depth.
+ * @return a vector containing the leaves
+ */
+
+ virtual std::vector<NodeId> getLeavesFromNode(NodeId node, unsigned int maxDepth) const = 0;
+
+ /**
+ * Get all leaves of a graph, ie, nodes with no son (or only one
+ * neighbor is not directet).
+ * @return a vector containing the leaves
+ */
+
+ virtual std::vector<NodeId> getAllLeaves() const = 0;
+
+ virtual std::set<NodeId> getSetOfAllLeaves() const = 0;
+
+ /**
+ * Get all the inner nodes, ie, nodes with degree > 1.
+ * @return a vector containing the nodes
+ */
+
+ virtual std::vector<NodeId> getAllInnerNodes() const = 0;
+
+ /**
+ * Get all the nodes.
+ * @return a vector containing the nodes
+ */
+
+ virtual std::vector<NodeId> getAllNodes() const = 0;
+
+ /**
+ * Get nodes located at the extremities of an edge
+ *
+ * @return a pair of the Nodes at each extremity of the edge
+ * example : N1--E1-->N2; getNodes(E1) will return (N1,N2);
+ */
+
+ virtual std::pair<NodeId, NodeId> getNodes(EdgeId edge) const = 0;
+
+ /**
+ * Get node located at the top of an edge
+ *
+ * @return the Node at the top the edge
+ * example : N1--E1-->N2; getTop(E1) will return N1;
+ */
+
+ virtual NodeId getTop(EdgeId edge) const = 0;
+
+ /**
+ * Get node located at the bottom of an edge
+ *
+ * @return the Node at the bottom the edge
+ * example : N1--E1-->N2; getBottom(E1) will return N2;
+ */
+
+ virtual NodeId getBottom(EdgeId edge) const = 0;
+
+ // /@}
+
+ /** @name Topological Properties
+ * These methodes check some topological properties.
+ */
+ // /@{
+
+ /**
+ * Is the graph a tree?
+ * @return false if a node is met more than one time browsing the graph
+ */
+
+ virtual bool isTree() const = 0;
+
+ /**
+ * Is the graph directed acyclic?
+ * @return true if an edge is met more than one time browsing the graph
+ */
+
+ virtual bool isDA() const = 0;
+
+
+ /**
+ * Orientates the graph hanging from the root
+ */
+
+ virtual void orientate() = 0;
+
+ /**
+ * Is the graph directed?
+ * @return true the type of the graph is directed
+ */
+
+ virtual bool isDirected() const = 0;
+
+
+ /**
+ * Does the graph contain reciprocal relations such as A->B and B->A?
+ * @return true if one of them is seen in the structure
+ */
+
+ virtual bool containsReciprocalRelations() const = 0;
+
+
+ // /@}
+
+
+ /** @name Edge Functions
+ * These methodes of the graph concern the edges.
+ */
+ // /@{
+
+ /**
+ * @name Iterator interface on Nodes
+ *
+ */
+
+ class EdgeIterator
+ {
+public:
+ virtual ~EdgeIterator() {}
+
+ virtual void next() = 0;
+ virtual bool end() const = 0;
+ virtual void start() = 0;
+
+ virtual EdgeId operator*() = 0;
+ };
+
+
+ /*
+ * @brief builds iterator on all Nodes of the graph
+ *
+ */
+
+ virtual std::unique_ptr<EdgeIterator> allEdgesIterator() = 0;
+
+ /*
+ * @brief builds iterator on the outgoing neighbor nodes of a Node
+ *
+ */
+
+ virtual std::unique_ptr<EdgeIterator> outgoingEdgesIterator(NodeId node) = 0;
+
+ /*
+ * @brief builds iterator on the incoming neighbor nodes of a Node
+ *
+ */
+
+ virtual std::unique_ptr<EdgeIterator> incomingEdgesIterator(NodeId node) = 0;
+
+ /**
+ * Get all the edges to/from a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the ID of the edges
+ */
+
+ virtual std::vector<EdgeId> getEdges(const NodeId node) const = 0;
+
+ /**
+ * In an directed graph, get all the edges which
+ * are leaving a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the ID of the outgoing edges
+ */
+
+ virtual std::vector<EdgeId> getOutgoingEdges(const NodeId node) const = 0;
+
+ /**
+ * In an directed graph, get all the edges which
+ * are coming to a node in the graph.
+ * @param node the node one wants to get its edges
+ * @return a vector containing the incoming edges
+ */
+
+ virtual std::vector<EdgeId> getIncomingEdges(NodeId node) const = 0;
+
+ /**
+ * Get all edges of a graph.
+ * @return a vector containing the edges
+ */
+
+ virtual std::vector<EdgeId> getAllEdges() const = 0;
+
+ /**
+ * Returns the Edge between two nodes
+ * @param nodeA if directed, origin node
+ * @param nodeB if directed, destination node
+ * @return the edge between these two nodes
+ */
+
+ virtual EdgeId getEdge(NodeId nodeA, NodeId nodeB) const = 0;
+
+ /**
+ * Returns the Edge between two nodes, trying both directions
+ * @param nodeA any node implied in the relation
+ * @param nodeB any other node implied in the relation
+ * @return the edge between these two nodes
+ */
+
+ virtual EdgeId getAnyEdge(NodeId nodeA, NodeId nodeB) const = 0;
+
+ // /@}
+
+protected:
+ /** @name Updating the changes on the observers
+ * These methodes aim to trigger some changes to the observers
+ */
+
+ // /@{
+
+ /**
+ * Trigger E objects deleting on the observers
+ * @param edgesToDelete list of edges to delete
+ */
+ virtual void notifyDeletedEdges(const std::vector<EdgeId>& edgesToDelete) const = 0;
+
+ /**
+ * Trigger N objects deleting on the observers
+ * @param nodesToDelete list of edges to delete
+ */
+ virtual void notifyDeletedNodes(const std::vector<NodeId>& nodesToDelete) const = 0;
+
+
+ // /@}
+
+public:
+ /**
+ * Output the graph in DOT format
+ * @param out a ostream where the DOT format will be output
+ * @param name a string naming the graph
+ */
+
+ virtual void outputToDot(std::ostream& out, const std::string& name) const = 0;
+
+ template<class N, class E, class GraphImpl>
+ friend class AssociationGraphImplObserver;
+};
+}
+
+#endif
diff --git a/src/Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.h b/src/Bpp/Graph/GraphObserver.h
similarity index 51%
copy from src/Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.h
copy to src/Bpp/Graph/GraphObserver.h
index ccf7fce..c1b8180 100644
--- a/src/Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.h
+++ b/src/Bpp/Graph/GraphObserver.h
@@ -1,14 +1,14 @@
//
-// File: CorrespondenceAnalysis.h
-// Created by: Mathieu Groussin
-// Created on: Sun Mar 06 10:03 2011
+// File GraphObserver.h
+// Created by: Thomas Bigot
+// Last modification : vendredi 4 novembre 2016, à 10h 21
//
/*
Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
- This software is a computer program whose purpose is to provide basal and
- utilitary classes. This file belongs to the Bio++ Project.
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
This software is governed by the CeCILL license under French law and
abiding by the rules of distribution of free software. You can use,
@@ -37,59 +37,62 @@
knowledge of the CeCILL license and that you accept its terms.
*/
+#ifndef _GRAPHOBSERVER_HPP_
+#define _GRAPHOBSERVER_HPP_
-#ifndef _CORRESPONDENCEANALYSIS_H_
-#define _CORRESPONDENCEANALYSIS_H_
+#include "Graph.h"
+
+#include "../Exceptions.h"
+#include "../Clonable.h"
+
+#include <vector>
+#include <map>
+#include <iostream>
+#include <ostream>
-#include "../../Matrix/Matrix.h"
-#include "DualityDiagram.h"
namespace bpp
-/**
- * @brief This class allows to perform a correspondence analysis.
- *
- * All values in the input table have to be non-negative.
- * The DualityDiagram class, core class of a multivariate analysis, is called internally.
- *
- * The code of this class is deeply inspired from the R code of the dudi.coa function available in the ade4 package.
- */
-{
-class CorrespondenceAnalysis:
- public DualityDiagram
{
-private:
- double n_;
-
-public:
/**
- * @brief Build a new CorrespondenceAnalysis object.
+ * @brief Defines a Graph Observer. It is a template which follows
+ * (subscribed to) a Graph.
+ * The graph and the graph observer communicate to keep them up-to-date
+ * each other. The observer is also an actor, since it can change
+ * the structure of the observed Graph.
*
- * @param data The input data (a RowMatrix) to analyse.
- * @param nbAxes The number of kept axes during the analysis.
- * @param tol Tolerance threshold for null eigenvalues (a value less than tol times the first one is considered as null)
- * @param verbose Should warnings be dispayed.
- * @throw Exception if an error occured.
+ * @author Thomas Bigot
*/
- CorrespondenceAnalysis(
- const Matrix<double>& data,
- unsigned int nbAxes,
- double tol = 0.0000001,
- bool verbose = true)
- throw (Exception);
- virtual ~CorrespondenceAnalysis() {}
-
-#ifndef NO_VIRTUAL_COV
- CorrespondenceAnalysis*
-#else
- Clonable*
-#endif
- clone() const { return new CorrespondenceAnalysis(*this); }
+// interface
+class GraphObserver :
+ public virtual Clonable
+{
public:
- double getSumOfAllValues() const throw (Exception) { return n_; }
+ /** @name Function called by the subjectGraph
+ * Methods called by the subject graph to make this observer so fit the subject graph
+ */
+ // /@{
+
+ /**
+ * Delete unused object edges, since they have been deleted in the graph
+ * @param edgesToDelete a vector of Edges to delete
+ */
+ virtual void deletedEdgesUpdate(const std::vector< unsigned int >& edgesToDelete) = 0;
+
+ /**
+ * Delete unused object nodes, since they have been deleted in the graph
+ * @param nodesToDelete a vector of N to delete
+ */
+ virtual void deletedNodesUpdate(const std::vector< unsigned int >& nodesToDelete) = 0;
+
+ // /@}
};
-} // end of namespace bpp.
+}
-#endif // _CORRESPONDENCEANALYSIS_H_
+#else
+
+namespace bpp
+{class GraphObserver; }
+#endif
diff --git a/src/Bpp/Graph/ONode.h b/src/Bpp/Graph/ONode.h
deleted file mode 100644
index c7ec781..0000000
--- a/src/Bpp/Graph/ONode.h
+++ /dev/null
@@ -1,170 +0,0 @@
-//
-// File: ONode.h
-// Author: Sylvain Gaillard
-// Created: 12/01/2011 08:36:47
-//
-
-/*
-Copyright or © or Copr. CNRS, (January 12, 2011)
-
-This software is a computer program whose purpose is to provide utilitary
-classes. This file belongs to the Bio++ Project.
-
-This software is governed by the CeCILL license under French law and
-abiding by the rules of distribution of free software. You can use,
-modify and/ or redistribute the software under the terms of the CeCILL
-license as circulated by CEA, CNRS and INRIA at the following URL
-"http://www.cecill.info".
-
-As a counterpart to the access to the source code and rights to copy,
-modify and redistribute granted by the license, users are provided only
-with a limited warranty and the software's author, the holder of the
-economic rights, and the successive licensors have only limited
-liability.
-
-In this respect, the user's attention is drawn to the risks associated
-with loading, using, modifying and/or developing or reproducing the
-software by the user in light of its specific status of free software,
-that may mean that it is complicated to manipulate, and that also
-therefore means that it is reserved for developers and experienced
-professionals having in-depth computer knowledge. Users are therefore
-encouraged to load and test the software's suitability as regards their
-requirements in conditions enabling the security of their systems and/or
-data to be ensured and, more generally, to use and operate it in the
-same conditions as regards security.
-
-The fact that you are presently reading this means that you have had
-knowledge of the CeCILL license and that you accept its terms.
-*/
-
-#ifndef _BPP_GRAPH_ONODE_H_
-#define _BPP_GRAPH_ONODE_H_
-
-#include "UNode.h"
-
-namespace bpp {
- /**
- * @brief Oriented Node interface
- *
- * ONode is an interface for oriented nodes aimed to build oriented graphs.
- *
- * @author Sylvain Gaillard
- */
- class ONode: public virtual UNode {
- public:
- /**
- * @name Neighbors
- *
- * @{
- */
-
- virtual const ONode * getNeighbor(int pos) const = 0;
- virtual ONode * getNeighbor(int pos) = 0;
-
- /** @} */
-
- /**
- * @name The Clonable interface.
- *
- * @{
- */
-#ifndef NO_VIRTUAL_COV
- ONode * clone() const = 0;
-#endif
- /** @} */
-
- /**
- * @name Fathers
- *
- * @{
- */
-
- /**
- * @brief Get a particular father in const environment.
- */
- virtual const ONode * getFather(int pos) const = 0;
-
- /**
- * @brief Get a particular father.
- */
- virtual ONode * getFather(int pos) = 0;
-
- /**
- * @brief Tell if this node has one or more father nodes.
- */
- virtual bool hasFathers() const = 0;
-
- /**
- * @brief Give the number of father nodes for this node.
- */
- virtual int getNumberOfFathers() const = 0;
-
- /** @} */
-
- /**
- * @name Sons
- *
- * @{
- */
-
- /**
- * @brief Get a particular son in const environment.
- */
- virtual const ONode * getSon(int pos) const = 0;
-
- /**
- * @brief Get a particular son.
- */
- virtual ONode * getSon(int pos) = 0;
-
- /**
- * @brief Tell if this node has one or more son nodes.
- */
- virtual bool hasSons() const = 0;
-
- /**
- * @brief Give the number of son nodes for this node.
- */
- virtual int getNumberOfSons() const = 0;
-
- /** @} */
-
- /**
- * @name Operators
- *
- * @{
- */
-
- /**
- * @brief Direct access to a neighbor in const context.
- *
- * - a positive i gives access to sons (from 0 to n - 1)
- * - a negative i gives access to fathers (from 1 to m)
- *
- * No check is done, you have to ensure that you query an existing
- * neighbor.
- *
- * @param i the position of the neighbor
- * @return A pointer toward the neighbor
- */
- virtual const ONode * operator[] (int i) const = 0;
-
- /**
- * @brief Direct access to a neighbor.
- *
- * - a positive i gives access to sons (from 0 to n - 1)
- * - a negative i gives access to fathers (from 1 to m)
- *
- * No check is done, you have to ensure that you query an existing
- * neighbor.
- *
- * @param i the position of the neighbor
- * @return A pointer toward the neighbor
- */
- virtual ONode * operator[] (int i) = 0;
-
- /** @} */
- };
-}
-
-#endif //_BPP_GRAPH_ONODE_H_
diff --git a/src/Bpp/Graph/TNode.h b/src/Bpp/Graph/TNode.h
deleted file mode 100644
index 71eecf5..0000000
--- a/src/Bpp/Graph/TNode.h
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// File: TNode.h
-// Author: Sylvain Gaillard
-// Created: 12/01/2011 08:43:15
-//
-
-/*
-Copyright or © or Copr. CNRS, (January 12, 2011)
-
-This software is a computer program whose purpose is to provide utilitary
-classes. This file belongs to the Bio++ Project.
-
-This software is governed by the CeCILL license under French law and
-abiding by the rules of distribution of free software. You can use,
-modify and/ or redistribute the software under the terms of the CeCILL
-license as circulated by CEA, CNRS and INRIA at the following URL
-"http://www.cecill.info".
-
-As a counterpart to the access to the source code and rights to copy,
-modify and redistribute granted by the license, users are provided only
-with a limited warranty and the software's author, the holder of the
-economic rights, and the successive licensors have only limited
-liability.
-
-In this respect, the user's attention is drawn to the risks associated
-with loading, using, modifying and/or developing or reproducing the
-software by the user in light of its specific status of free software,
-that may mean that it is complicated to manipulate, and that also
-therefore means that it is reserved for developers and experienced
-professionals having in-depth computer knowledge. Users are therefore
-encouraged to load and test the software's suitability as regards their
-requirements in conditions enabling the security of their systems and/or
-data to be ensured and, more generally, to use and operate it in the
-same conditions as regards security.
-
-The fact that you are presently reading this means that you have had
-knowledge of the CeCILL license and that you accept its terms.
-*/
-
-#ifndef _BPP_GRAPH_TNODE_H_
-#define _BPP_GRAPH_TNODE_H_
-
-#include "ONode.h"
-
-namespace bpp {
- /**
- * @brief Tree Node interface
- *
- * TNode is an interface for tree nodes (i.e. oriented nodes with only one
- * father). It is aimed to build trees.
- *
- * @author Sylvain Gaillard
- */
- class TNode: public virtual ONode {
- public:
- /**
- * @name Neighbors
- *
- * @{
- */
-
- /**
- * @copydoc bpp::ONode::getNeighbor(int) const
- */
- virtual const TNode * getNeighbor(int pos) const = 0;
-
- /**
- * @copydoc bpp::ONode::getNeighbor(int)
- */
- virtual TNode * getNeighbor(int pos) = 0;
-
- /** @} */
-
- /**
- * @name The Clonable interface.
- *
- * @{
- */
-#ifndef NO_VIRTUAL_COV
- TNode * clone() const = 0;
-#endif
- /** @} */
-
- /**
- * @name Fathers
- *
- * @{
- */
-
- virtual const TNode * getFather(int pos) const = 0;
- virtual TNode * getFather(int pos) = 0;
-
- /**
- * @brief Get the father in const environment.
- */
- virtual const TNode * getFather() const = 0;
-
- /**
- * @brief Get the father.
- */
- virtual TNode * getFather() = 0;
-
- /** @} */
-
- /**
- * @name Sons
- *
- * @{
- */
-
- virtual const TNode * getSon(int pos) const = 0;
- virtual TNode * getSon(int pos) = 0;
-
- /** @} */
-
- /**
- * @name Operators
- *
- * @{
- */
-
- virtual const TNode * operator[] (int i) const = 0;
- virtual TNode * operator[] (int i) = 0;
-
- /** @} */
- };
-}
-
-#endif //_BPP_GRAPH_TNODE_H_
diff --git a/src/Bpp/Graph/TreeGraph.h b/src/Bpp/Graph/TreeGraph.h
new file mode 100644
index 0000000..c791507
--- /dev/null
+++ b/src/Bpp/Graph/TreeGraph.h
@@ -0,0 +1,201 @@
+//
+// File TreeGraph.h
+// Created by: Thomas Bigot
+// Last modification : vendredi 4 novembre 2016, à 10h 25
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+
+#ifndef _TREEGRAPH_H_
+#define _TREEGRAPH_H_
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <ostream>
+
+
+#include "Graph.h"
+
+#include "../Exceptions.h"
+#include "../Numeric/VectorTools.h"
+
+namespace bpp
+{
+class TreeGraph :
+ public virtual Graph
+{
+public:
+ /**
+ * Is the graph a tree? A tree must be acyclic and with no isolated node.
+ * @return true if valid tree
+ */
+ virtual bool isValid() const = 0;
+
+ /**
+ * Get the father node of a node in a rooted tree
+ * @return the father node
+ */
+
+ virtual Graph::NodeId getFather(Graph::NodeId nodeid) const = 0;
+
+ /**
+ * Get the branch leading to the father in a rooted tree
+ * @return the branch between a node and its father
+ */
+
+ virtual Graph::EdgeId getEdgeToFather(Graph::NodeId node) const = 0;
+
+ /**
+ * Check if node has a father
+ */
+
+ virtual bool hasFather(Graph::NodeId node) const = 0;
+
+ /**
+ * Says if a node is a leaf (ie has at most one neighbor).
+ */
+
+ virtual bool isLeaf(Graph::NodeId node) const = 0;
+
+ /**
+ * Get the leaves under a node
+ * @param node the starting node
+ * @return a vector containing the leaves
+ */
+
+ virtual std::vector<Graph::NodeId> getLeavesUnderNode(Graph::NodeId node) const = 0;
+
+ /**
+ * Get the sons node of a node
+ */
+
+ virtual std::vector<Graph::NodeId> getSons(Graph::NodeId node) const = 0;
+
+ /**
+ * Get the branches to the sons of a node
+ */
+
+ virtual std::vector<Graph::EdgeId> getBranches(Graph::NodeId node) const = 0;
+
+ /**
+ * Get a iterator on the sons node of a node
+ */
+
+ virtual std::unique_ptr<Graph::NodeIterator> sonsIterator(Graph::NodeId node) = 0;
+
+ /**
+ * Get a iterator on the branches to sons of a node
+ */
+
+ virtual std::unique_ptr<Graph::EdgeIterator> branchesIterator(Graph::NodeId node) = 0;
+
+ /**
+ * @brief Get the number of sons node
+ */
+
+ virtual size_t getNumberOfSons(Graph::NodeId node) const = 0;
+
+ /**
+ * set the father node of a node in a rooted tree
+ */
+
+ virtual void setFather(Graph::NodeId node, Graph::NodeId fatherNode) = 0;
+
+ virtual void setFather(Graph::NodeId node, Graph::NodeId fatherNode, Graph::EdgeId edgeId) = 0;
+
+ /**
+ * Add a son to a node in a rooted tree
+ */
+
+ virtual void addSon(Graph::NodeId node, Graph::NodeId sonNode) = 0;
+
+ virtual void addSon(Graph::NodeId node, Graph::NodeId sonNode, Graph::EdgeId edgeId) = 0;
+
+ /**
+ * Remove all the sons
+ */
+
+ std::vector<Graph::NodeId> removeSons(Graph::NodeId node);
+
+ /**
+ * Remove one son
+ */
+
+ virtual void removeSon(Graph::NodeId node, Graph::NodeId son) = 0;
+
+ /**
+ * Re-root the tree with the new root
+ */
+
+ virtual void rootAt(Graph::NodeId newRoot) = 0;
+
+ /**
+ * Set the tree to its flat unrooted version.
+ * As an algorithmical convenience, a root node is kept, but it has
+ * no logical significance.
+ */
+
+ virtual void unRoot(bool joinRootSons) = 0;
+
+ /**
+ * Set a node as a new outgroup in a rooted tree, will make a root between
+ * the given node and its father.
+ */
+
+ virtual void setOutGroup(Graph::NodeId newOutGroup) = 0;
+
+ /**
+ * Get all the nodes of a subtree
+ */
+
+ virtual std::vector<Graph::NodeId> getSubtreeNodes(Graph::NodeId localRoot) const = 0;
+
+ /**
+ * Get all the branches of a subtree
+ */
+
+ virtual std::vector<Graph::EdgeId> getSubtreeEdges(Graph::NodeId localRoot) const = 0;
+
+ // ///FROM TREETOOLS & TREETOOLS COMPAT
+
+
+ virtual std::vector<Graph::NodeId> getNodePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB, bool includeAncestor = true) const = 0;
+ virtual std::vector<Graph::EdgeId> getEdgePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB) const = 0;
+};
+}
+
+
+#endif
diff --git a/src/Bpp/Graph/TreeGraphImpl.h b/src/Bpp/Graph/TreeGraphImpl.h
new file mode 100644
index 0000000..c51bf1e
--- /dev/null
+++ b/src/Bpp/Graph/TreeGraphImpl.h
@@ -0,0 +1,593 @@
+//
+// File TreeGraphImpl.h
+// Created by: Thomas Bigot
+// Last modification : vendredi 4 novembre 2016, à 10h 21
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide utilitary
+ classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
+
+#ifndef _TREEGRAPH_IMPL_H_
+#define _TREEGRAPH_IMPL_H_
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <ostream>
+
+
+#include "TreeGraph.h"
+#include "GlobalGraph.h"
+
+#include "../Exceptions.h"
+#include "../Numeric/VectorTools.h"
+
+namespace bpp
+{
+template<class GraphImpl>
+class TreeGraphImpl :
+ public virtual TreeGraph,
+ public GraphImpl
+{
+private:
+ /**
+ * Is the graph a tree? Set to false when structure is modified, true after validation.
+ */
+ mutable bool isValid_;
+
+ // unvalidate the tree
+ void topologyHasChanged_() const;
+
+ // will throw an exception if the tree is not valid
+ void mustBeValid_() const;
+
+ // will throw an exception if the tree is not rooted
+ void mustBeRooted_() const;
+
+ // test the validity of the tree
+ bool validate_() const;
+
+ /**
+ * Reorient all the edges starting from a node:
+ * the father node becomes a son, and so on.
+ */
+ void propagateDirection_(Graph::NodeId node);
+
+ // recursive function for getSubtreeNodes
+ void fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const;
+
+ // recursive function for getSubtreeEdges
+ void fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const;
+
+ // recursive function for getLeavesUnderNode
+ void fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const;
+
+public:
+ TreeGraphImpl();
+
+ TreeGraphImpl(bool rooted = true);
+
+ /**
+ * Is the graph a tree? A tree must be acyclic and with no isolated node.
+ * @return true if valid tree
+ */
+ bool isValid() const;
+
+ /**
+ * Is the tree rooted?
+ *
+ * @return true if rooted, ie is directed.
+ */
+
+ bool isRooted() const;
+
+ /**
+ * Get the father node of a node in a rooted tree
+ * @return the father node
+ */
+
+ Graph::NodeId getFather(Graph::NodeId nodeid) const;
+
+ /**
+ * Get the branch leading to the father in a rooted tree
+ * @return the branch between a node and its father
+ */
+
+ Graph::EdgeId getEdgeToFather(Graph::NodeId node) const;
+
+ /**
+ * Check if node has a father
+ */
+
+ bool hasFather(Graph::NodeId node) const;
+
+ /**
+ * Says if a node is a leaf (ie has at most one neighbor).
+ */
+
+ bool isLeaf(Graph::NodeId node) const;
+
+ /**
+ * Get the leaves under a node
+ * @param node the starting node
+ * @return a vector containing the leaves
+ */
+
+ std::vector<Graph::NodeId> getLeavesUnderNode(Graph::NodeId node) const;
+
+ /**
+ * Get the sons node of a node
+ */
+
+ std::vector<Graph::NodeId> getSons(Graph::NodeId node) const;
+
+ /**
+ * Get the branches to the sons node of a node
+ */
+
+ std::vector<Graph::EdgeId> getBranches(Graph::NodeId node) const;
+
+ /**
+ * Get a iterator on the sons node of a node
+ */
+
+ std::unique_ptr<Graph::NodeIterator> sonsIterator(Graph::NodeId node);
+
+ /**
+ * Get a iterator on the branches to sons of a node
+ */
+
+ std::unique_ptr<Graph::EdgeIterator> branchesIterator(Graph::NodeId node);
+
+ /**
+ * @brief Get the number of sons node
+ */
+
+ size_t getNumberOfSons(Graph::NodeId node) const;
+
+ /**
+ * set the father node of a node in a rooted tree
+ */
+
+ void setFather(Graph::NodeId node, Graph::NodeId fatherNode);
+ void setFather(Graph::NodeId node, Graph::NodeId fatherNode, Graph::EdgeId edgeId);
+
+ /**
+ * Add a son to a node in a rooted tree
+ */
+
+ void addSon(Graph::NodeId node, Graph::NodeId sonNode);
+
+ void addSon(Graph::NodeId node, Graph::NodeId sonNode, Graph::EdgeId edgeId);
+
+ /**
+ * Remove all the sons
+ */
+
+ std::vector<Graph::NodeId> removeSons(Graph::NodeId node);
+
+ /**
+ * Remove one son
+ */
+
+ void removeSon(Graph::NodeId node, Graph::NodeId son);
+
+ /**
+ * Re-root the tree with the new root
+ */
+
+ void rootAt(Graph::NodeId newRoot);
+
+ /**
+ * Set the tree to its flat unrooted version.
+ * As an algorithmical convenience, a root node is kept, but it has
+ * no logical significance.
+ */
+
+ void unRoot(bool joinRootSons);
+
+ /**
+ * Set a node as a new outgroup in a rooted tree, will make a root between
+ * the given node and its father.
+ */
+
+ void setOutGroup(Graph::NodeId newOutGroup);
+
+ /**
+ * Get all the nodes of a subtree
+ */
+
+ std::vector<Graph::NodeId> getSubtreeNodes(Graph::NodeId localRoot) const;
+
+ /**
+ * Get all the branches of a subtree
+ */
+
+ std::vector<Graph::EdgeId> getSubtreeEdges(Graph::NodeId localRoot) const;
+
+ // ///FROM TREETOOLS & TREETOOLS COMPAT
+
+
+ std::vector<Graph::NodeId> getNodePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB, bool includeAncestor = true) const;
+ std::vector<Graph::EdgeId> getEdgePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB) const;
+};
+
+
+/******************/
+
+typedef TreeGraphImpl<GlobalGraph> TreeGlobalGraph;
+
+/*****************/
+
+
+template<class GraphImpl>
+TreeGraphImpl<GraphImpl>::TreeGraphImpl(bool rooted) :
+ GraphImpl(rooted),
+ isValid_(false)
+{}
+
+
+template<class GraphImpl>
+bool TreeGraphImpl<GraphImpl>::isValid() const
+{
+ return isValid_ || validate_();
+}
+
+template<class GraphImpl>
+Graph::NodeId TreeGraphImpl<GraphImpl>::getFather(Graph::NodeId node) const
+{
+ std::vector<Graph::NodeId> incomers = getIncomingNeighbors(node);
+ if (incomers.size() > 1)
+ throw Exception("TreeGraphImpl<GraphImpl>::getFather: more than one father for Node " + TextTools::toString(node) + " : " + VectorTools::paste(incomers, ",") + ". Should never happen since validity has been controled. Please report this bug.");
+ if (incomers.size() == 0)
+ throw Exception("TreeGraphImpl<GraphImpl>::getFather: node " + TextTools::toString(node) + " has no father.");
+ return *incomers.begin();
+}
+
+template<class GraphImpl>
+Graph::EdgeId TreeGraphImpl<GraphImpl>::getEdgeToFather(Graph::NodeId node) const
+{
+ Graph::NodeId father = getFather(node);
+ return GraphImpl::getEdge(father, node);
+}
+
+template<class GraphImpl>
+bool TreeGraphImpl<GraphImpl>::hasFather(Graph::NodeId node) const
+{
+ return GraphImpl::getNumberOfIncomingNeighbors(node) >= 1;
+}
+
+template<class GraphImpl>
+bool TreeGraphImpl<GraphImpl>::isLeaf(Graph::NodeId node) const
+{
+ return (!GraphImpl::isDirected() && GraphImpl::getNumberOfOutgoingNeighbors(node) <= 1)
+ || (GraphImpl::isDirected() && GraphImpl::getNumberOfOutgoingNeighbors(node) == 0);
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const
+{
+ const std::vector<Graph::NodeId> sons = getSons(startingNode);
+ if (sons.size() > 1)
+ {
+ for (std::vector<Graph::NodeId>::const_iterator currNeighbor = sons.begin(); currNeighbor != sons.end(); currNeighbor++)
+ {
+ fillListOfLeaves_(*currNeighbor, foundLeaves);
+ }
+ }
+ else
+ {
+ foundLeaves.push_back(startingNode);
+ }
+}
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getLeavesUnderNode(Graph::NodeId node) const
+{
+ std::vector<Graph::NodeId> foundLeaves;
+ fillListOfLeaves_(node, foundLeaves);
+
+ return foundLeaves;
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::mustBeRooted_() const
+{
+ if (!isRooted())
+ throw Exception("TreeGraphImpl<GraphImpl>: The tree must be rooted.");
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::mustBeValid_() const
+{
+ if (!isValid())
+ throw Exception("TreeGraphImpl<GraphImpl>: The tree is not valid.");
+}
+
+template<class GraphImpl>
+bool TreeGraphImpl<GraphImpl>::isRooted() const
+{
+ return GraphImpl::isDirected();
+}
+
+template<class GraphImpl>
+bool TreeGraphImpl<GraphImpl>::validate_() const
+{
+ isValid_ = GraphImpl::isTree();
+ return isValid_;
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::topologyHasChanged_() const
+{
+ isValid_ = false;
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::rootAt(Graph::NodeId newRoot)
+{
+ if (!isValid())
+ throw Exception("TreeGraphImpl::rootAt: Tree is not Valid.");
+
+ GraphImpl::makeDirected();
+ // set the new root on the Graph
+ GraphImpl::setRoot(newRoot);
+ // change edge direction between the new node and the former one
+ propagateDirection_(newRoot);
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::propagateDirection_(Graph::NodeId node)
+{
+ if (hasFather(node))
+ {
+ NodeId father = getFather(node);
+ propagateDirection_(father);
+ GraphImpl::switchNodes(father, node);
+ }
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::setFather(Graph::NodeId node, Graph::NodeId fatherNode)
+{
+ if (hasFather(node))
+ GraphImpl::unlink(getFather(node), node);
+ GraphImpl::link(fatherNode, node);
+ topologyHasChanged_();
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::setFather(Graph::NodeId node, Graph::NodeId fatherNode, Graph::EdgeId edgeId)
+{
+ if (hasFather(node))
+ GraphImpl::unlink(getFather(node), node);
+ GraphImpl::link(fatherNode, node, edgeId);
+ topologyHasChanged_();
+}
+
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::addSon(Graph::NodeId node, Graph::NodeId sonNode)
+{
+ GraphImpl::link(node, sonNode);
+ topologyHasChanged_();
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::addSon(Graph::NodeId node, Graph::NodeId sonNode, Graph::EdgeId edgeId)
+{
+ GraphImpl::link(node, sonNode, edgeId);
+ topologyHasChanged_();
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::unRoot(bool joinRootSons)
+{
+ if (joinRootSons)
+ {
+ // the root must have exactly two joinRootSons
+ std::vector<Graph::NodeId> sons = getSons(GraphImpl::getRoot());
+ if (sons.size() != 2)
+ throw Exception("The root must have two sons to join them.");
+ GraphImpl::unlink(GraphImpl::getRoot(), sons.at(0));
+ GraphImpl::unlink(GraphImpl::getRoot(), sons.at(1));
+ GraphImpl::link(sons.at(0), sons.at(1));
+ GraphImpl::setRoot(sons.at(0));
+ }
+ GraphImpl::makeUndirected();
+}
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getSons(Graph::NodeId node) const
+{
+ return GraphImpl::getOutgoingNeighbors(node);
+}
+
+template<class GraphImpl>
+std::vector<Graph::EdgeId> TreeGraphImpl<GraphImpl>::getBranches(Graph::NodeId node) const
+{
+ return GraphImpl::getOutgoingEdges(node);
+}
+
+template<class GraphImpl>
+std::unique_ptr<Graph::NodeIterator> TreeGraphImpl<GraphImpl>::sonsIterator(Graph::NodeId node)
+{
+ return GraphImpl::outgoingNeighborNodesIterator(node);
+}
+
+template<class GraphImpl>
+std::unique_ptr<Graph::EdgeIterator> TreeGraphImpl<GraphImpl>::branchesIterator(Graph::NodeId node)
+{
+ return GraphImpl::outgoingEdgesIterator(node);
+}
+
+template<class GraphImpl>
+size_t TreeGraphImpl<GraphImpl>::getNumberOfSons(Graph::NodeId node) const
+{
+ return GraphImpl::getNumberOfOutgoingNeighbors(node);
+}
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::removeSons(Graph::NodeId node)
+{
+ std::vector<Graph::NodeId> sons = getSons(node);
+ for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
+ {
+ removeSon(node, *currSon);
+ }
+ return sons;
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::removeSon(Graph::NodeId node, Graph::NodeId son)
+{
+ GraphImpl::unlink(node, son);
+ topologyHasChanged_();
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::setOutGroup(Graph::NodeId newOutGroup)
+{
+ mustBeRooted_();
+ deleteNode(GraphImpl::getRoot());
+
+ Graph::NodeId newRoot = GraphImpl::createNodeFromEdge(getEdge(getFather(newOutGroup), newOutGroup));
+ rootAt(newRoot);
+}
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getNodePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB, bool includeAncestor) const
+{
+ GraphImpl::nodeMustExist_(nodeA);
+ GraphImpl::nodeMustExist_(nodeB);
+ std::vector<Graph::NodeId> path;
+ std::vector<Graph::NodeId> pathMatrix1;
+ std::vector<Graph::NodeId> pathMatrix2;
+
+ Graph::NodeId nodeUp = nodeA;
+ while (hasFather(nodeUp))
+ {
+ pathMatrix1.push_back(nodeUp);
+ nodeUp = getFather(nodeUp);
+ }
+ pathMatrix1.push_back(nodeUp); // The root.
+
+ nodeUp = nodeB;
+ while (hasFather(nodeUp))
+ {
+ pathMatrix2.push_back(nodeUp);
+ nodeUp = getFather(nodeUp);
+ }
+ pathMatrix2.push_back(nodeUp); // The root.
+ // Must check that the two nodes have the same root!!!
+
+ size_t tmp1 = pathMatrix1.size();
+ size_t tmp2 = pathMatrix2.size();
+
+ while ((tmp1 > 0) && (tmp2 > 0))
+ {
+ if (pathMatrix1[tmp1 - 1] != pathMatrix2[tmp2 - 1])
+ break;
+ tmp1--; tmp2--;
+ }
+ // (tmp1 - 1) and (tmp2 - 1) now point toward the first non-common nodes
+
+ for (size_t y = 0; y < tmp1; ++y)
+ {
+ path.push_back(pathMatrix1[y]);
+ }
+ if (includeAncestor) // FIXME: one of the extremities may be the ancestor!!!
+ path.push_back(pathMatrix1[tmp1]); // pushing once, the Node that was common to both.
+ for (size_t j = tmp2; j > 0; --j)
+ {
+ path.push_back(pathMatrix2[j - 1]);
+ }
+ return path;
+}
+
+template<class GraphImpl>
+std::vector<Graph::EdgeId> TreeGraphImpl<GraphImpl>::getEdgePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB) const
+{
+ std::vector<Graph::EdgeId> path;
+ std::vector<Graph::NodeId> pathNodes = getNodePathBetweenTwoNodes(nodeA, nodeB, true);
+ for (size_t currNodeNr = 0; currNodeNr + 1 < pathNodes.size(); currNodeNr++)
+ {
+ path.push_back(GraphImpl::getAnyEdge(pathNodes.at(currNodeNr), pathNodes.at(currNodeNr + 1)));
+ }
+ return path;
+}
+
+template<class GraphImpl>
+std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getSubtreeNodes(Graph::NodeId localRoot) const
+{
+ mustBeValid_();
+ std::vector<Graph::EdgeId> metNodes;
+ fillSubtreeMetNodes_(metNodes, localRoot);
+ return metNodes;
+}
+
+template<class GraphImpl>
+std::vector<Graph::EdgeId> TreeGraphImpl<GraphImpl>::getSubtreeEdges(Graph::NodeId localRoot) const
+{
+ mustBeValid_();
+ std::vector<Graph::EdgeId> metEdges;
+ fillSubtreeMetEdges_(metEdges, localRoot);
+ return metEdges;
+}
+
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const
+{
+ metNodes.push_back(localRoot);
+ std::vector<Graph::NodeId> sons = GraphImpl::getOutgoingNeighbors(localRoot);
+ for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
+ {
+ fillSubtreeMetNodes_(metNodes, *currSon);
+ }
+}
+
+template<class GraphImpl>
+void TreeGraphImpl<GraphImpl>::fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const
+{
+ std::vector<Graph::EdgeId> edgesToSons = GraphImpl::getOutgoingEdges(localRoot);
+ for (std::vector<Graph::EdgeId>::iterator currEdgeToSon = edgesToSons.begin(); currEdgeToSon != edgesToSons.end(); currEdgeToSon++)
+ {
+ metEdges.push_back(*currEdgeToSon);
+ fillSubtreeMetEdges_(metEdges, GraphImpl::getBottom(*currEdgeToSon));
+ }
+}
+}
+
+
+#endif
diff --git a/src/Bpp/Graph/UNode.h b/src/Bpp/Graph/UNode.h
deleted file mode 100644
index 86053a5..0000000
--- a/src/Bpp/Graph/UNode.h
+++ /dev/null
@@ -1,123 +0,0 @@
-//
-// File: UNode.h
-// Author: Sylvain Gaillard
-// Created: 12/01/2011 08:33:55
-//
-
-/*
-Copyright or © or Copr. CNRS, (January 12, 2011)
-
-This software is a computer program whose purpose is to provide utilitary
-classes. This file belongs to the Bio++ Project.
-
-This software is governed by the CeCILL license under French law and
-abiding by the rules of distribution of free software. You can use,
-modify and/ or redistribute the software under the terms of the CeCILL
-license as circulated by CEA, CNRS and INRIA at the following URL
-"http://www.cecill.info".
-
-As a counterpart to the access to the source code and rights to copy,
-modify and redistribute granted by the license, users are provided only
-with a limited warranty and the software's author, the holder of the
-economic rights, and the successive licensors have only limited
-liability.
-
-In this respect, the user's attention is drawn to the risks associated
-with loading, using, modifying and/or developing or reproducing the
-software by the user in light of its specific status of free software,
-that may mean that it is complicated to manipulate, and that also
-therefore means that it is reserved for developers and experienced
-professionals having in-depth computer knowledge. Users are therefore
-encouraged to load and test the software's suitability as regards their
-requirements in conditions enabling the security of their systems and/or
-data to be ensured and, more generally, to use and operate it in the
-same conditions as regards security.
-
-The fact that you are presently reading this means that you have had
-knowledge of the CeCILL license and that you accept its terms.
-*/
-
-#ifndef _BPP_GRAPH_UNODE_H_
-#define _BPP_GRAPH_UNODE_H_
-
-#include "../Clonable.h"
-
-// From the STL
-#include <vector>
-
-namespace bpp {
- /**
- * @brief Unoriented node interface
- *
- * UNode is an interface for unoriented nodes aimed to build unoriented
- * graphs.
- *
- * In these classes we choose to use int for positions rathed than size_t
- * because negative positions are used in some implementations to distinguish
- * between two types of neighbors in operator[]. @see bpp::ONode
- *
- * @author Sylvain Gaillard
- */
- class UNode: public virtual Clonable {
- public:
- /**
- * @name Neighbors
- *
- * @{
- */
-
- /**
- * @brief Get a neighbor of this node in const context.
- *
- * @param pos the position of the neighbor to get.
- * @return A pointer toward the neighbor node.
- */
- virtual const UNode * getNeighbor(int pos) const = 0;
-
- /**
- * @brief Get a neighbor of this node.
- *
- * @param pos the position of the neighbor to get.
- * @return A pointer toward the neighbor node.
- */
- virtual UNode * getNeighbor(int pos) = 0;
-
- /**
- * @brief Get the degree i.e. the number of neighbors of this node.
- */
- virtual int degree() const = 0;
-
- /** @} */
-
- /**
- * @name The Clonable interface.
- *
- * @{
- */
-#ifndef NO_VIRTUAL_COV
- UNode * clone() const = 0;
-#endif
- /** @} */
-
- /**
- * @name Operators
- *
- * @{
- */
-
- /**
- * @brief Direct access to a neighbor in const context.
- */
- virtual const UNode * operator[] (int i) const = 0;
-
- /**
- * @brief Direct access to a neighbor.
- */
- virtual UNode * operator[] (int i) = 0;
-
- /** @} */
-
- };
-}
-
-#endif //_BPP_GRAPH_UNODE_H_
diff --git a/src/Bpp/Graphics/Font/Font.h b/src/Bpp/Graphics/Font/Font.h
index 1a3b36c..2e8b8f8 100644
--- a/src/Bpp/Graphics/Font/Font.h
+++ b/src/Bpp/Graphics/Font/Font.h
@@ -73,12 +73,7 @@ class Font:
virtual ~Font() {}
-#ifdef NO_VIRTUAL_COV
- Clonable*
-#else
- Font*
-#endif
- clone() const { return new Font(*this); }
+ Font* clone() const { return new Font(*this); }
private:
void init_();
diff --git a/src/Bpp/Graphics/Font/FontManager.h b/src/Bpp/Graphics/Font/FontManager.h
index 541f530..6f8889c 100644
--- a/src/Bpp/Graphics/Font/FontManager.h
+++ b/src/Bpp/Graphics/Font/FontManager.h
@@ -46,6 +46,7 @@ knowledge of the CeCILL license and that you accept its terms.
#include <vector>
#include "../../Text/TextTools.h"
+#include "../../Exceptions.h"
namespace bpp
{
diff --git a/src/Bpp/Graphics/RgbColor.h b/src/Bpp/Graphics/RgbColor.h
index 5e0fdfd..7ba3215 100644
--- a/src/Bpp/Graphics/RgbColor.h
+++ b/src/Bpp/Graphics/RgbColor.h
@@ -66,12 +66,7 @@ class RGBColor:
RGBColor(): red_(0), green_(0), blue_(0) {}
virtual ~RGBColor() {}
-#ifdef NO_VIRTUAL_COV
- Clonable*
-#else
- RGBColor*
-#endif
- clone() const { return new RGBColor(*this); }
+ RGBColor* clone() const { return new RGBColor(*this); }
public:
bool operator==(const RGBColor & color) const
diff --git a/src/Bpp/Io/BppODiscreteDistributionFormat.cpp b/src/Bpp/Io/BppODiscreteDistributionFormat.cpp
index 8ae25f0..7fdbc2a 100644
--- a/src/Bpp/Io/BppODiscreteDistributionFormat.cpp
+++ b/src/Bpp/Io/BppODiscreteDistributionFormat.cpp
@@ -72,7 +72,7 @@ DiscreteDistribution* BppODiscreteDistributionFormat::read(
{
unparsedArguments_.clear();
string distName;
- auto_ptr<DiscreteDistribution> rDist;
+ unique_ptr<DiscreteDistribution> rDist;
map<string, string> args;
KeyvalTools::parseProcedure(distDescription, distName, args);
@@ -208,11 +208,26 @@ DiscreteDistribution* BppODiscreteDistributionFormat::read(
if (distName == "Gamma")
{
- rDist.reset(new GammaDiscreteDistribution(nbClasses, 1, 1));
+ double offset=0;
+
+ if (args.find("offset") != args.end())
+ try
+ {
+ offset=TextTools::toDouble(args["offset"]);
+ }
+ catch (Exception& e) {}
+
+ if (args.find("ParamOffset") != args.end())
+ rDist.reset(new GammaDiscreteDistribution(nbClasses, 1, 1, true, offset));
+ else
+ rDist.reset(new GammaDiscreteDistribution(nbClasses, 1, 1, false, offset));
+
if (args.find("alpha") != args.end())
unparsedArguments_["Gamma.alpha"] = args["alpha"];
if (args.find("beta") != args.end())
unparsedArguments_["Gamma.beta"] = args["beta"];
+ if (args.find("offset") != args.end())
+ unparsedArguments_["Gamma.offset"] = args["offset"];
}
else if (distName == "Gaussian")
{
diff --git a/src/Bpp/Io/OutputStream.h b/src/Bpp/Io/OutputStream.h
index 5c6d363..6c1aaef 100644
--- a/src/Bpp/Io/OutputStream.h
+++ b/src/Bpp/Io/OutputStream.h
@@ -87,9 +87,7 @@ public:
*
* @{
*/
-#ifndef NO_VIRTUAL_COV
OutputStream* clone() const = 0;
-#endif
/** @} */
};
@@ -169,14 +167,14 @@ class StlOutputStream :
public AbstractOutputStream
{
private:
- mutable std::auto_ptr<std::ostream> stream_;
+ mutable std::unique_ptr<std::ostream> stream_;
public:
StlOutputStream(std::ostream* stream): stream_(stream) {}
- StlOutputStream(const StlOutputStream& stlos) : stream_(stlos.stream_) {}
+ StlOutputStream(const StlOutputStream& stlos) : stream_() { stream_ = std::move(stlos.stream_); }
StlOutputStream& operator=(const StlOutputStream& stlos)
{
- stream_ = stlos.stream_;
+ stream_ = std::move(stlos.stream_);
return *this;
}
@@ -326,9 +324,7 @@ public:
OutputStream& endLine() { std::cerr << std::endl; return *this; }
OutputStream& flush() { std::cerr.flush(); return *this; }
-#ifndef NO_VIRTUAL_COV
StdErr* clone() const { return new StdErr(*this); }
-#endif
};
diff --git a/src/Bpp/Numeric/AbstractParameterAliasable.cpp b/src/Bpp/Numeric/AbstractParameterAliasable.cpp
index 353cf8c..ce7c5ba 100644
--- a/src/Bpp/Numeric/AbstractParameterAliasable.cpp
+++ b/src/Bpp/Numeric/AbstractParameterAliasable.cpp
@@ -45,9 +45,12 @@ using namespace std;
AbstractParameterAliasable::AbstractParameterAliasable(const AbstractParameterAliasable& ap) :
AbstractParametrizable(ap),
- independentParameters_(ap.independentParameters_),
+ independentParameters_(),
aliasListenersRegister_()
{
+ for (size_t i=0; i<ap.independentParameters_.size(); i++)
+ independentParameters_.shareParameter(getSharedParameter(getParameterNameWithoutNamespace(ap.independentParameters_[i].getName())));
+
// Actualize the register with adequate pointers:
for (map<string, AliasParameterListener*>::const_iterator it = ap.aliasListenersRegister_.begin();
it != ap.aliasListenersRegister_.end();
@@ -56,9 +59,11 @@ AbstractParameterAliasable::AbstractParameterAliasable(const AbstractParameterAl
AliasParameterListener* listener = it->second->clone();
listener->setParameterList(&getParameters_());
aliasListenersRegister_[it->first] = listener;
- //Now correct parameters with appropriate pointers:
- for (unsigned int i = 0; i < getNumberOfParameters(); ++i) {
- if (getParameters_()[i].hasParameterListener(it->first)) {
+ // Now correct parameters with appropriate pointers:
+ for (unsigned int i = 0; i < getNumberOfParameters(); ++i)
+ {
+ if (getParameters_()[i].hasParameterListener(it->first))
+ {
getParameters_()[i].removeParameterListener(it->first);
getParameters_()[i].addParameterListener(listener, false);
}
@@ -68,7 +73,10 @@ AbstractParameterAliasable::AbstractParameterAliasable(const AbstractParameterAl
AbstractParameterAliasable& AbstractParameterAliasable::operator=(const AbstractParameterAliasable& ap)
{
- independentParameters_ = ap.independentParameters_;
+ AbstractParametrizable::operator=(ap);
+
+ for (size_t i=0; i<ap.independentParameters_.size(); i++)
+ independentParameters_.shareParameter(getSharedParameter(getParameterNameWithoutNamespace(ap.independentParameters_[i].getName())));
// Actualize the register with adequate pointers:
for (map<string, AliasParameterListener*>::const_iterator it = ap.aliasListenersRegister_.begin();
@@ -78,9 +86,11 @@ AbstractParameterAliasable& AbstractParameterAliasable::operator=(const Abstract
AliasParameterListener* listener = it->second->clone();
listener->setParameterList(&getParameters_());
aliasListenersRegister_[it->first] = listener;
- //Now correct parameters with appropriate pointers:
- for (unsigned int i = 0; i < getNumberOfParameters(); ++i) {
- if (getParameters_()[i].hasParameterListener(it->first)) {
+ // Now correct parameters with appropriate pointers:
+ for (unsigned int i = 0; i < getNumberOfParameters(); ++i)
+ {
+ if (getParameters_()[i].hasParameterListener(it->first))
+ {
getParameters_()[i].removeParameterListener(it->first);
getParameters_()[i].addParameterListener(listener, false);
}
@@ -105,7 +115,7 @@ throw (ParameterNotFoundException, Exception)
{
// In case this is the first time we call this method:
if (getNumberOfParameters() > 0 && independentParameters_.size() == 0)
- independentParameters_ = getParameters();
+ independentParameters_.shareParameters(getParameters());
if (!hasParameter(p1))
throw ParameterNotFoundException("AbstractParameterAliasable::aliasParameters", p1);
@@ -125,55 +135,65 @@ throw (ParameterNotFoundException, Exception)
if (!param1->hasConstraint())
{
if (param2->hasConstraint())
- throw Exception("AbstractParameterAliasable::aliasParameters. Cannot alias parameter " + p2 + " to " + p1 + ", because the constraints attached to these two parameters are different.");
+ {
+ ApplicationTools::displayWarning("Aliasing parameter " + p2 + " to " + p1 + ". " + p1 + " gets the constraints of " + p2 + ": " + param2->getConstraint()->getDescription());
+ param1->setConstraint(param2->getConstraint());
+ }
}
else
- // We use a small trick here, we test the constraints on the basis of their string description (C++ does not provide a default operator==() :( ).
+ // We use a small trick here, we test the constraints on the basis of their string description (C++ does not provide a default operator==() :( ).
if (param2->hasConstraint() && (param1->getConstraint()->getDescription() != param2->getConstraint()->getDescription()))
- throw Exception("AbstractParameterAliasable::aliasParameters. Cannot alias parameter " + p2 + " to " + p1 + ", because the constraints attached to these two parameters are different.");
-
+ {
+ Constraint* nc = *param2->getConstraint() & *param1->getConstraint();
+ ApplicationTools::displayWarning("Aliasing parameter " + p2 + " to " + p1 + " with different constraints. They get the intersection of both constraints : " + nc->getDescription());
+
+ param2->setConstraint(nc, true);
+ param1->setConstraint(nc->clone(), true);
+ }
+
// Every thing seems ok, let's create the listener and register it:
AliasParameterListener* aliasListener = new AliasParameterListener(id, getParameters().whichParameterHasName(getNamespace() + p2), &getParameters_(), p1);
- ParameterList pl=getParameters_();
-
aliasListenersRegister_[id] = aliasListener;
// Now we add it to the appropriate parameter, that is p1.
// The parameter will not own the listener, the bookkeeping being achieved by the register:
param1->addParameterListener(aliasListener, false);
+
// Finally we remove p2 from the list of independent parameters:
independentParameters_.deleteParameter(getNamespace() + p2);
-
}
void AbstractParameterAliasable::aliasParameters(map<string, string>& unparsedParams, bool verbose)
{
- ParameterList plpars, pl=getParameters();
-
- for (size_t i=0; i< pl.size(); i++)
+ const ParameterList& pl = getParameters();
+ ParameterList plpars;
+
+ for (size_t i = 0; i < pl.size(); i++)
{
- if (unparsedParams.find(pl[i].getName())==unparsedParams.end())
+ if (unparsedParams.find(pl[i].getName()) == unparsedParams.end())
plpars.addParameter(*pl[i].clone());
}
- size_t unp_s=unparsedParams.size();
- while (unp_s!=0)
+ size_t unp_s = unparsedParams.size();
+ while (unp_s != 0)
{
map<string, string>::iterator it;
- for (it=unparsedParams.begin(); it!=unparsedParams.end(); it++)
+ for (it = unparsedParams.begin(); it != unparsedParams.end(); it++)
{
- Parameter* pp=0;
- try {
- pp=&plpars.getParameter(it->second);
+ Parameter* pp = 0;
+ try
+ {
+ pp = &plpars.getParameter(it->second);
}
- catch (ParameterNotFoundException& e){
+ catch (ParameterNotFoundException& e)
+ {
if (!pl.hasParameter(it->second))
- throw ParameterNotFoundException("Unknown aliasing parameter", it->second);
+ throw ParameterNotFoundException("Unknown aliasing parameter", it->first + "->" + it->second);
continue;
}
- auto_ptr<Parameter> p2(pp->clone());
+ unique_ptr<Parameter> p2(pp->clone());
p2->setName(it->first);
plpars.addParameter(p2.release());
plpars.getParameter(it->first);
@@ -183,17 +203,15 @@ void AbstractParameterAliasable::aliasParameters(map<string, string>& unparsedPa
unparsedParams.erase(it);
}
- if (unparsedParams.size()==unp_s)
- throw Exception("Error, there is a cycle in aliasing");
+ if (unparsedParams.size() == unp_s)
+ throw Exception("Error, there is a cycle in aliasing starting with " + unparsedParams.begin()->first);
else
- unp_s=unparsedParams.size();
+ unp_s = unparsedParams.size();
}
matchParametersValues(plpars);
}
-
-
void AbstractParameterAliasable::unaliasParameters(const std::string& p1, const std::string& p2)
throw (ParameterNotFoundException, Exception)
@@ -212,22 +230,14 @@ throw (ParameterNotFoundException, Exception)
delete it->second;
aliasListenersRegister_.erase(it);
// Finally we re-add p2 to the list of independent parameters:
- independentParameters_.addParameter(getParameter(p2));
+ independentParameters_.shareParameter(getSharedParameter(p2));
}
void AbstractParameterAliasable::setNamespace(const std::string& prefix)
{
string currentName;
- // First we correct the independent parameter list
- for (unsigned int i = 0; i < independentParameters_.size(); i++)
- {
- currentName = independentParameters_[i].getName();
- if (TextTools::startsWith(currentName, getNamespace()))
- independentParameters_[i].setName(prefix + currentName.substr(getNamespace().size()));
- else
- independentParameters_[i].setName(prefix + currentName);
- }
- // Then we modify all the listeners
+
+ // We modify all the listeners
for (map<string, AliasParameterListener*>::iterator it = aliasListenersRegister_.begin();
it != aliasListenersRegister_.end();
it++)
@@ -238,7 +248,8 @@ void AbstractParameterAliasable::setNamespace(const std::string& prefix)
else
it->second->rename(prefix + currentName);
}
- // Finally we notify the mother class:
+
+// Finally we notify the mother class:
AbstractParametrizable::setNamespace(prefix);
}
@@ -254,7 +265,8 @@ vector<string> AbstractParameterAliasable::getAlias(const string& name) const
{
string alias = it->second->getAlias();
aliases.push_back(alias);
- if (alias!=name){
+ if (alias != name)
+ {
vector<string> chainAliases = getAlias(alias);
VectorTools::append(aliases, chainAliases);
}
@@ -263,61 +275,123 @@ vector<string> AbstractParameterAliasable::getAlias(const string& name) const
return aliases;
}
+
+std::map<std::string, std::string> AbstractParameterAliasable::getAliases() const
+{
+ map<string, string> aliases;
+
+ for (map<string, AliasParameterListener*>::const_iterator it = aliasListenersRegister_.begin();
+ it != aliasListenersRegister_.end();
+ it++)
+ {
+ string name = it->second->getFrom();
+
+ vector<string> alias = getAlias(name);
+
+ for (size_t i = 0; i < alias.size(); i++)
+ {
+ aliases[alias[i]] = name;
+ }
+ }
+
+ return aliases;
+}
+
ParameterList AbstractParameterAliasable::getAliasedParameters(const ParameterList& pl) const
{
ParameterList aliases;
- bool b=false;
-
+ bool b = false;
+
for (map<string, AliasParameterListener*>::const_iterator it = aliasListenersRegister_.begin();
it != aliasListenersRegister_.end();
it++)
{
if ((pl.hasParameter(it->second->getFrom()) ||
aliases.hasParameter(it->second->getFrom()))
- && ! (aliases.hasParameter(it->second->getAlias()) ||
- pl.hasParameter(it->second->getAlias())))
+ && !(aliases.hasParameter(it->second->getAlias()) ||
+ pl.hasParameter(it->second->getAlias())))
{
- b=true;
+ b = true;
aliases.addParameter(getParameter(it->second->getAlias()));
}
}
-
+
while (b)
{
- b=false;
-
+ b = false;
+
for (map<string, AliasParameterListener*>::const_iterator it = aliasListenersRegister_.begin();
it != aliasListenersRegister_.end();
it++)
{
if (aliases.hasParameter(it->second->getFrom())
- && ! (aliases.hasParameter(it->second->getAlias()) ||
- pl.hasParameter(it->second->getAlias())))
+ && !(aliases.hasParameter(it->second->getAlias()) ||
+ pl.hasParameter(it->second->getAlias())))
{
- b=true;
+ b = true;
aliases.addParameter(getParameter(it->second->getAlias()));
}
}
}
-
+
return aliases;
}
string AbstractParameterAliasable::getFrom(const string& name) const
{
- string from="";
-
+ string from = "";
+
for (map<string, AliasParameterListener*>::const_iterator it = aliasListenersRegister_.begin();
it != aliasListenersRegister_.end();
it++)
+ {
+ if (it->second->getName() == name)
{
- if (it->second->getName() == name)
- {
- from = it->second->getFrom();
- break;
- }
+ from = it->second->getFrom();
+ break;
}
+ }
return from;
}
+
+ParameterList AbstractParameterAliasable::getFromParameters(const ParameterList& pl) const
+{
+ ParameterList from;
+ bool b = false;
+
+ for (map<string, AliasParameterListener*>::const_iterator it = aliasListenersRegister_.begin();
+ it != aliasListenersRegister_.end();
+ it++)
+ {
+ if ((pl.hasParameter(it->second->getAlias()) ||
+ from.hasParameter(it->second->getAlias()))
+ && !(from.hasParameter(it->second->getFrom()) ||
+ pl.hasParameter(it->second->getFrom())))
+ {
+ b = true;
+ from.addParameter(getParameter(it->second->getFrom()));
+ }
+ }
+
+ while (b)
+ {
+ b = false;
+
+ for (map<string, AliasParameterListener*>::const_iterator it = aliasListenersRegister_.begin();
+ it != aliasListenersRegister_.end();
+ it++)
+ {
+ if (from.hasParameter(it->second->getAlias())
+ && !(from.hasParameter(it->second->getFrom()) ||
+ pl.hasParameter(it->second->getFrom())))
+ {
+ b = true;
+ from.addParameter(getParameter(it->second->getFrom()));
+ }
+ }
+ }
+
+ return from;
+}
diff --git a/src/Bpp/Numeric/AbstractParameterAliasable.h b/src/Bpp/Numeric/AbstractParameterAliasable.h
index 1fc4157..4db3441 100644
--- a/src/Bpp/Numeric/AbstractParameterAliasable.h
+++ b/src/Bpp/Numeric/AbstractParameterAliasable.h
@@ -5,37 +5,37 @@
//
/*
- Copyright or © or Copr. Bio++ Development Team, (November 19, 2004)
-
- This software is a computer program whose purpose is to provide classes
- for numerical calculus.
-
- This software is governed by the CeCILL license under French law and
- abiding by the rules of distribution of free software. You can use,
- modify and/ or redistribute the software under the terms of the CeCILL
- license as circulated by CEA, CNRS and INRIA at the following URL
- "http://www.cecill.info".
-
- As a counterpart to the access to the source code and rights to copy,
- modify and redistribute granted by the license, users are provided only
- with a limited warranty and the software's author, the holder of the
- economic rights, and the successive licensors have only limited
- liability.
-
- In this respect, the user's attention is drawn to the risks associated
- with loading, using, modifying and/or developing or reproducing the
- software by the user in light of its specific status of free software,
- that may mean that it is complicated to manipulate, and that also
- therefore means that it is reserved for developers and experienced
- professionals having in-depth computer knowledge. Users are therefore
- encouraged to load and test the software's suitability as regards their
- requirements in conditions enabling the security of their systems and/or
- data to be ensured and, more generally, to use and operate it in the
- same conditions as regards security.
-
- The fact that you are presently reading this means that you have had
- knowledge of the CeCILL license and that you accept its terms.
-*/
+ Copyright or © or Copr. Bio++ Development Team, (November 19, 2004)
+
+ This software is a computer program whose purpose is to provide classes
+ for numerical calculus.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+ */
#ifndef _ABSTRACTPARAMETERALIASABLE_H_
#define _ABSTRACTPARAMETERALIASABLE_H_
@@ -43,218 +43,239 @@
#include "AbstractParametrizable.h"
#include "ParameterAliasable.h"
-//From the STL:
+// From the STL:
#include <map>
namespace bpp
{
-
- /**
- * @brief Inner listener class used by AbstractParameterAliasable.
- */
- class AliasParameterListener:
- public ParameterListener
+/**
+ * @brief Inner listener class used by AbstractParameterAliasable.
+ */
+class AliasParameterListener :
+ public ParameterListener
+{
+private:
+ std::string id_;
+ size_t alias_;
+ ParameterList* pl_;
+ std::string name_;
+ std::string from_;
+
+public:
+ AliasParameterListener(const std::string& id, size_t alias, ParameterList* pl, const std::string& from) :
+ id_(id),
+ alias_(alias),
+ pl_(pl),
+ name_(),
+ from_(from)
{
- private:
- std::string id_;
- size_t alias_;
- ParameterList *pl_;
- std::string name_;
- std::string from_;
-
- public:
- AliasParameterListener(const std::string& id, size_t alias, ParameterList* pl, const std::string& from):
- id_(id),
- alias_(alias),
- pl_(pl),
- name_(),
- from_(from)
- {
- //This allow us to check if the parameter position have changed at some point...
- name_ = (*pl_)[alias].getName();
- }
+ // This allow us to check if the parameter position have changed at some point...
+ name_ = (*pl_)[alias].getName();
+ }
- AliasParameterListener(const AliasParameterListener& apl):
+ AliasParameterListener(const AliasParameterListener& apl) :
id_(apl.id_),
alias_(apl.alias_),
pl_(apl.pl_),
name_(apl.name_),
from_(apl.from_)
- {}
+ {}
- AliasParameterListener& operator=(const AliasParameterListener& apl)
- {
- id_ = apl.id_;
- alias_ = apl.alias_;
- pl_ = apl.pl_;
- name_ = apl.name_;
- from_ = apl.from_;
- return *this;
- }
+ AliasParameterListener& operator=(const AliasParameterListener& apl)
+ {
+ id_ = apl.id_;
+ alias_ = apl.alias_;
+ pl_ = apl.pl_;
+ name_ = apl.name_;
+ from_ = apl.from_;
+ return *this;
+ }
- AliasParameterListener* clone() const { return new AliasParameterListener(*this); }
+ AliasParameterListener* clone() const { return new AliasParameterListener(*this); }
- public:
- const std::string& getId() const { return id_; }
+public:
+ const std::string& getId() const { return id_; }
- const std::string& getFrom() const { return from_; }
-
- void setParameterList(ParameterList* pl) { pl_ = pl; }
+ const std::string& getFrom() const { return from_; }
- void parameterNameChanged(ParameterEvent& event) throw (Exception) {}
-
- void parameterValueChanged(ParameterEvent& event) throw (Exception)
- {
- Parameter* p = &(*pl_)[alias_];
- if (p->getName() != name_)
- throw Exception("AbstractParameterAliasable::AliasParameterListener::parameterValueChanged. Error, aliased parameter have change, maybe because it was renamed, or a parameter was removed?");
- p->setValue(event.getParameter()->getValue());
- }
+ void setParameterList(ParameterList* pl) { pl_ = pl; }
+
+ void parameterNameChanged(ParameterEvent& event) throw (Exception) {}
+
+ void parameterValueChanged(ParameterEvent& event) throw (Exception)
+ {
+ Parameter* p = &(*pl_)[alias_];
+ if (p->getName() != name_)
+ throw Exception("AbstractParameterAliasable::AliasParameterListener::parameterValueChanged. Error, aliased parameter have change, maybe because it was renamed, or a parameter was removed?");
+ p->setValue(event.getParameter()->getValue());
+ }
+
+ const std::string& getName() const { return name_; }
+
+ void rename(const std::string& name) { name_ = name; }
+
+ const std::string& getAlias() const { return (*pl_)[alias_].getName(); }
+};
+
+/**
+ * @brief A partial implementation of the Parametrizable interface.
+ *
+ * Parameters are stored in a protected ParameterList object.
+ *
+ * The abstract fireParameterChanged() method is provided so that the derived class
+ * know when a parameter has changed, and can be updated.
+ * All methods call the corresponding method in ParameterList and then call the
+ * fireParameterChanged() method.
+ */
+class AbstractParameterAliasable :
+ public AbstractParametrizable,
+ public virtual ParameterAliasable
+{
+private:
+ mutable ParameterList independentParameters_;
+
+ /**
+ * Contains all parameter listeners for maintening alias relationships.
+ * The registry will be updated appropriately upon cloning and deleting.
+ */
+ std::map<std::string, AliasParameterListener*> aliasListenersRegister_;
- const std::string& getName() const { return name_; }
+public:
+ AbstractParameterAliasable(const std::string& prefix) :
+ AbstractParametrizable(prefix),
+ independentParameters_(),
+ aliasListenersRegister_()
+ {}
- void rename(const std::string& name) { name_ = name; }
+ AbstractParameterAliasable(const AbstractParameterAliasable& ap);
- const std::string& getAlias() const { return (*pl_)[alias_].getName(); }
-
- };
+ AbstractParameterAliasable& operator=(const AbstractParameterAliasable& ap);
+
+ virtual ~AbstractParameterAliasable();
+
+public:
+ void setNamespace(const std::string& prefix);
+
+ bool hasIndependentParameter(const std::string& name) const { return independentParameters_.hasParameter(getNamespace() + name); }
+
+ const ParameterList& getIndependentParameters() const { return independentParameters_; }
+
+ size_t getNumberOfIndependentParameters() const { return independentParameters_.size(); }
+
+ void aliasParameters(const std::string& p1, const std::string& p2) throw (ParameterNotFoundException, Exception);
+
+ void unaliasParameters(const std::string& p1, const std::string& p2) throw (ParameterNotFoundException, Exception);
+
+ /**
+ * @brief alias the parameters following the links described in a
+ * map, and update the object accordingly. Cycles in aliasing are
+ * detected and forbidden.
+ *
+ * @param unparsedParams the map of the links : <A,B> matches for A->B aliasing.
+ * @param verbose verbosity
+ *
+ **/
+
+ void aliasParameters(std::map<std::string, std::string>& unparsedParams, bool verbose);
/**
- * @brief A partial implementation of the Parametrizable interface.
+ * @brief Return the list of the names of the parameters that are
+ * aliased (directly or not) to one of the parameters of the list.
*
- * Parameters are stored in a protected ParameterList object.
+ */
+
+ ParameterList getAliasedParameters(const ParameterList& pl) const;
+
+ /**
+ * @brief Return the list of the names of the parameters from which
+ * the parameters of the list are aliased (directly or not).
*
- * The abstract fireParameterChanged() method is provided so that the derived class
- * know when a parameter has changed, and can be updated.
- * All methods call the corresponding method in ParameterList and then call the
- * fireParameterChanged() method.
*/
- class AbstractParameterAliasable:
- public AbstractParametrizable,
- public virtual ParameterAliasable
+
+ ParameterList getFromParameters(const ParameterList& pl) const;
+
+
+ /**
+ * @return The list of names of the parameters that are aliased with a given parameter.
+ * The implementation is recursive, which means that in the case of A->B->C, getalias(C) will return both A and B.
+ * @param name The name of the parameter to look for.
+ */
+
+ virtual std::vector<std::string> getAlias(const std::string& name) const;
+
+ /**
+ * @return the map of the aliases.
+ *
+ **/
+
+ virtual std::map<std::string, std::string> getAliases() const;
+
+ /**
+ * @return The name of the parameter from which a given parameter is aliased.
+ * @param name The name of the parameter to look for.
+ */
+
+ std::string getFrom(const std::string& name) const;
+
+ // void fireParameterChanged(const ParameterList& parameters)
+ // {
+ // independentParameters_.matchParametersValues(getParameters());
+ // }
+
+protected:
+ void addParameter_(Parameter* parameter)
{
- private:
-
- mutable ParameterList independentParameters_;
-
- /**
- * Contains all parameter listeners for maintening alias relationships.
- * The registry will be updated appropriately upon cloning and deleting.
- */
- std::map<std::string, AliasParameterListener *> aliasListenersRegister_;
-
- public:
- AbstractParameterAliasable(const std::string& prefix) :
- AbstractParametrizable(prefix),
- independentParameters_(),
- aliasListenersRegister_()
- {}
-
- AbstractParameterAliasable(const AbstractParameterAliasable& ap);
-
- AbstractParameterAliasable& operator=(const AbstractParameterAliasable& ap);
-
- virtual ~AbstractParameterAliasable();
-
- public:
- void setNamespace(const std::string& prefix);
-
- const ParameterList& getIndependentParameters() const { return independentParameters_; }
-
- size_t getNumberOfIndependentParameters() const { return independentParameters_.size(); }
-
- void aliasParameters(const std::string& p1, const std::string& p2) throw (ParameterNotFoundException, Exception);
-
- void unaliasParameters(const std::string& p1, const std::string& p2) throw (ParameterNotFoundException, Exception);
-
- /**
- * @brief alias the parameters following the links described in a
- * map, and update the object accordingly. Cycles in aliasing are
- * detected and forbidden.
- *
- * @param unparsedParams the map of the links : <A,B> matches for A->B aliasing.
- * @param verbose verbosity
- *
- **/
-
- void aliasParameters(std::map<std::string, std::string>& unparsedParams, bool verbose);
-
- /**
- * @brief Return the list of the names of the parameters that are
- * aliased (directly or not) to one of the parameters of the list.
- *
- */
-
- ParameterList getAliasedParameters(const ParameterList& pl) const;
-
-
- /**
- * @return The list of names of the parameters that are aliased with a given parameter.
- * The implementation is recursive, which means that in the case of A->B->C, getalias(C) will return both A and B.
- * @param name The name of the parameter to look for.
- */
-
- std::vector<std::string> getAlias(const std::string& name) const;
-
- /**
- * @return The name of the parameter from which a given parameter is aliased.
- * @param name The name of the parameter to look for.
- */
-
- std::string getFrom(const std::string& name) const;
-
- void fireParameterChanged(const ParameterList& parameters)
- {
- independentParameters_.matchParametersValues(getParameters());
- }
+ AbstractParametrizable::addParameter_(parameter);
+ independentParameters_.shareParameter(getSharedParameter(getParameterNameWithoutNamespace(parameter->getName())));
+ }
- protected:
- void addParameter_(Parameter* parameter)
- {
- AbstractParametrizable::addParameter_(parameter);
- independentParameters_.addParameter(parameter->clone());
- }
+ void addParameters_(const ParameterList& parameters)
+ {
+ AbstractParametrizable::addParameters_(parameters);
- void addParameters_(const ParameterList& parameters)
- {
- AbstractParametrizable::addParameters_(parameters);
- independentParameters_.addParameters(parameters);
- }
+ for (size_t i=0; i<parameters.size(); i++)
+ independentParameters_.shareParameter(getSharedParameter(getParameterNameWithoutNamespace(parameters[i].getName())));
+ }
- void deleteParameter_(size_t index) throw (IndexOutOfBoundsException)
- {
- std::string name = getParameter_(index).getName();
- AbstractParametrizable::deleteParameter_(index);
- if (independentParameters_.hasParameter(name))
- independentParameters_.deleteParameter(name);
- }
+ void includeParameters_(const ParameterList& parameters)
+ {
+ AbstractParametrizable::includeParameters_(parameters);
+ for (size_t i=0; i<parameters.size(); i++)
+ independentParameters_.shareParameter(getSharedParameter(getParameterNameWithoutNamespace(parameters[i].getName())));
+ }
- void deleteParameter_(std::string& name) throw (IndexOutOfBoundsException)
- {
- AbstractParametrizable::deleteParameter_(name);
- if (independentParameters_.hasParameter(name))
- independentParameters_.deleteParameter(name);
- }
- void deleteParameters_(const std::vector<std::string>& names)
- {
- std::string x;
- for (size_t i=0; i<names.size(); i++)
- {
- x=names[i];
- deleteParameter_(x);
- }
- }
+ void deleteParameter_(size_t index) throw (IndexOutOfBoundsException)
+ {
+ std::string name = getParameterNameWithoutNamespace(getParameter_(index).getName());
+ AbstractParametrizable::deleteParameter_(index);
+ if (independentParameters_.hasParameter(name))
+ independentParameters_.deleteParameter(name);
+ }
+
+ void deleteParameter_(std::string& name) throw (IndexOutOfBoundsException)
+ {
+ AbstractParametrizable::deleteParameter_(name);
+ if (independentParameters_.hasParameter(name))
+ independentParameters_.deleteParameter(name);
+ }
- void resetParameters_()
+ void deleteParameters_(const std::vector<std::string>& names)
+ {
+ std::string x;
+ for (size_t i = 0; i < names.size(); i++)
{
- AbstractParametrizable::resetParameters_();
- independentParameters_.reset();
+ x = names[i];
+ deleteParameter_(x);
}
+ }
- };
-
-} //end of namespace bpp.
-
-#endif //_ABSTRACTPARAMETERALIASABLE_H_
+ void resetParameters_()
+ {
+ AbstractParametrizable::resetParameters_();
+ independentParameters_.reset();
+ }
+};
+} // end of namespace bpp.
+#endif // _ABSTRACTPARAMETERALIASABLE_H_
diff --git a/src/Bpp/Numeric/AbstractParametrizable.h b/src/Bpp/Numeric/AbstractParametrizable.h
index a023d83..4aa989f 100644
--- a/src/Bpp/Numeric/AbstractParametrizable.h
+++ b/src/Bpp/Numeric/AbstractParametrizable.h
@@ -80,7 +80,12 @@ class AbstractParametrizable:
{
return parameters_.getParameter(prefix_ + name);
}
-
+
+ const std::shared_ptr<Parameter>& getSharedParameter(const std::string& name) const throw (ParameterNotFoundException)
+ {
+ return parameters_.getSharedParameter(prefix_ + name);
+ }
+
double getParameterValue(const std::string& name) const
throw (ParameterNotFoundException)
{
@@ -111,7 +116,7 @@ class AbstractParametrizable:
bool matchParametersValues(const ParameterList& parameters)
throw (ConstraintException)
{
- std::auto_ptr< std::vector<size_t> >updatedParameters(new std::vector<size_t>());
+ std::unique_ptr< std::vector<size_t> >updatedParameters(new std::vector<size_t>());
bool test = parameters_.matchParametersValues(parameters, updatedParameters.get());
if (test)
fireParameterChanged(parameters.subList(*updatedParameters));
@@ -131,41 +136,60 @@ class AbstractParametrizable:
*
* @param parameters A ParameterList object with parameters that changed.
*/
- virtual void fireParameterChanged(const ParameterList& parameters) = 0;
+
+ virtual void fireParameterChanged(const ParameterList& parameters) {};
+
+
protected:
- void addParameter_(Parameter* parameter)
- {
- if (parameter)
- parameters_.addParameter(parameter);
- }
+
+ virtual void addParameter_(Parameter* parameter)
+ {
+ if (parameter)
+ parameters_.addParameter(parameter);
+ }
+
+ virtual void addParameters_(const ParameterList& parameters)
+ {
+ parameters_.addParameters(parameters);
+ }
- void addParameters_(const ParameterList& parameters)
- {
- parameters_.addParameters(parameters);
- }
+ void shareParameter_(const std::shared_ptr<Parameter>& parameter)
+ {
+ parameters_.shareParameter(parameter);
+ }
- void deleteParameter_(size_t index) throw (IndexOutOfBoundsException)
- {
- if (index >= parameters_.size())
- throw IndexOutOfBoundsException("AbstractParametrizable::deleteParameter_.", index, 0, parameters_.size() - 1);
- parameters_.deleteParameter(index);
- }
+ void shareParameters_(const ParameterList& parameters)
+ {
+ parameters_.shareParameters(parameters);
+ }
+
+ virtual void includeParameters_(const ParameterList& parameters)
+ {
+ parameters_.includeParameters(parameters);
+ }
+
+ virtual void deleteParameter_(size_t index) throw (IndexOutOfBoundsException)
+ {
+ if (index >= parameters_.size())
+ throw IndexOutOfBoundsException("AbstractParametrizable::deleteParameter_.", index, 0, parameters_.size() - 1);
+ parameters_.deleteParameter(index);
+ }
- void deleteParameter_(std::string& name)
+ virtual void deleteParameter_(std::string& name)
{
parameters_.deleteParameter(name);
}
- void deleteParameters_(const std::vector<std::string>& names)
+ virtual void deleteParameters_(const std::vector<std::string>& names)
{
parameters_.deleteParameters(names);
}
- void resetParameters_()
- {
- parameters_.reset();
- }
+ void resetParameters_()
+ {
+ parameters_.reset();
+ }
/**
* @param name The name of the parameter.
@@ -202,14 +226,31 @@ class AbstractParametrizable:
throw IndexOutOfBoundsException("AbstractParametrizable::getParameter_.", index, 0, parameters_.size() - 1);
return parameters_[index];
}
- const Parameter& getParameter_(size_t index) const throw (IndexOutOfBoundsException)
+
+ const Parameter& getParameter_(size_t index) const throw (IndexOutOfBoundsException)
{
if(index >= parameters_.size())
throw IndexOutOfBoundsException("AbstractParametrizable::getParameter_.", index, 0, parameters_.size() - 1);
return parameters_[index];
}
-
- ParameterList& getParameters_() { return parameters_; }
+
+
+ ParameterList& getParameters_() { return parameters_; }
+
+ /**
+ * @return The shared_ptr parameter at a given position.
+ * @warning No check is performed on the validity of the index given as input!
+ */
+ const std::shared_ptr<Parameter>& getSharedParameter(size_t i) const
+ {
+ return parameters_.getSharedParameter(i);
+ }
+
+ std::shared_ptr<Parameter>& getSharedParameter(size_t i)
+ {
+ return parameters_.getSharedParameter(i);
+ }
+
};
} //end of namespace bpp.
diff --git a/src/Bpp/Numeric/AutoParameter.cpp b/src/Bpp/Numeric/AutoParameter.cpp
index 3289be9..7093a3b 100644
--- a/src/Bpp/Numeric/AutoParameter.cpp
+++ b/src/Bpp/Numeric/AutoParameter.cpp
@@ -5,37 +5,37 @@
//
/*
- Copyright or © or Copr. CNRS, (November 17, 2004)
-
- This software is a computer program whose purpose is to provide classes
- for numerical calculus.
-
- This software is governed by the CeCILL license under French law and
- abiding by the rules of distribution of free software. You can use,
- modify and/ or redistribute the software under the terms of the CeCILL
- license as circulated by CEA, CNRS and INRIA at the following URL
- "http://www.cecill.info".
-
- As a counterpart to the access to the source code and rights to copy,
- modify and redistribute granted by the license, users are provided only
- with a limited warranty and the software's author, the holder of the
- economic rights, and the successive licensors have only limited
- liability.
-
- In this respect, the user's attention is drawn to the risks associated
- with loading, using, modifying and/or developing or reproducing the
- software by the user in light of its specific status of free software,
- that may mean that it is complicated to manipulate, and that also
- therefore means that it is reserved for developers and experienced
- professionals having in-depth computer knowledge. Users are therefore
- encouraged to load and test the software's suitability as regards their
- requirements in conditions enabling the security of their systems and/or
- data to be ensured and, more generally, to use and operate it in the
- same conditions as regards security.
-
- The fact that you are presently reading this means that you have had
- knowledge of the CeCILL license and that you accept its terms.
-*/
+ * Copyright or © or Copr. CNRS, (November 17, 2004)
+ *
+ * This software is a computer program whose purpose is to provide classes
+ * for numerical calculus.
+ *
+ * This software is governed by the CeCILL license under French law and
+ * abiding by the rules of distribution of free software. You can use,
+ * modify and/ or redistribute the software under the terms of the CeCILL
+ * license as circulated by CEA, CNRS and INRIA at the following URL
+ * "http://www.cecill.info".
+ *
+ * As a counterpart to the access to the source code and rights to copy,
+ * modify and redistribute granted by the license, users are provided only
+ * with a limited warranty and the software's author, the holder of the
+ * economic rights, and the successive licensors have only limited
+ * liability.
+ *
+ * In this respect, the user's attention is drawn to the risks associated
+ * with loading, using, modifying and/or developing or reproducing the
+ * software by the user in light of its specific status of free software,
+ * that may mean that it is complicated to manipulate, and that also
+ * therefore means that it is reserved for developers and experienced
+ * professionals having in-depth computer knowledge. Users are therefore
+ * encouraged to load and test the software's suitability as regards their
+ * requirements in conditions enabling the security of their systems and/or
+ * data to be ensured and, more generally, to use and operate it in the
+ * same conditions as regards security.
+ *
+ * The fact that you are presently reading this means that you have had
+ * knowledge of the CeCILL license and that you accept its terms.
+ */
#include "AutoParameter.h"
#include "NumConstants.h"
@@ -59,7 +59,7 @@ string AutoParameter::CONSTRAINTS_KEEP = "keep";
/** Constructors: *************************************************************/
AutoParameter::AutoParameter(const std::string& name, double value, Constraint* constraint, bool attachConstraint) throw (ConstraintException):
- Parameter(name, value, constraint, attachConstraint), messageHandler_(ApplicationTools::message) {}
+Parameter(name, value, constraint, attachConstraint), messageHandler_(ApplicationTools::message) {}
AutoParameter::AutoParameter(const Parameter& p): Parameter(p), messageHandler_(ApplicationTools::message) {}
@@ -69,51 +69,51 @@ AutoParameter& AutoParameter::operator=(const AutoParameter& p)
{
Parameter::operator=(p);
messageHandler_ = p.messageHandler_;
- return *this;
+ return *this;
}
/******************************************************************************/
-
+
void AutoParameter::setValue(double value) throw (ConstraintException)
{
try
- {
- // First we try to assign this value:
- Parameter::setValue(value);
- }
+ {
+ // First we try to assign this value:
+ Parameter::setValue(value);
+ }
catch (ConstraintException& ce)
+ {
+ // Aie, there's a pb here...
+ if (messageHandler_)
+ {
+ (*messageHandler_) << "Constraint match at parameter ";
+ (*messageHandler_) << name_;
+ (*messageHandler_) << ", badValue = ";
+ (*messageHandler_) << ce.getBadValue();
+ (*messageHandler_) << " ";
+ (*messageHandler_ << constraint_->getDescription()).endLine();
+ }
+ double limit = constraint_->getAcceptedLimit(value);
+ try
+ { // We try to assign the limit then.
+ Parameter::setValue(limit);
+ }
+ catch(ConstraintException& ce2)
{
- // Aie, there's a pb here...
- if (messageHandler_)
- {
- (*messageHandler_) << "Constraint match at parameter ";
- (*messageHandler_) << name_;
- (*messageHandler_) << ", badValue = ";
- (*messageHandler_) << ce.getBadValue();
- (*messageHandler_) << " ";
- (*messageHandler_ << constraint_->getDescription()).endLine();
- }
- double limit = constraint_->getAcceptedLimit(value);
+ // Aie, the limit is not reachable, so we perform a smaller step...
+ //Parameter::setValue((getValue() + limit) / 2);
try
- { // We try to assign the limit then.
- Parameter::setValue(limit);
- }
- catch(ConstraintException& ce2)
- {
- // Aie, the limit is not reachable, so we perform a smaller step...
- //Parameter::setValue((getValue() + limit) / 2);
- try
- {
- // Try on the right:
- Parameter::setValue(limit + NumConstants::TINY());
- }
- catch(ConstraintException& ce3)
- {
- // Try on the left:
- Parameter::setValue(limit - NumConstants::TINY());
- }
- }
+ {
+ // Try on the right:
+ Parameter::setValue(limit + NumConstants::TINY());
+ }
+ catch(ConstraintException& ce3)
+ {
+ // Try on the left:
+ Parameter::setValue(limit - NumConstants::TINY());
+ }
}
+ }
}
/******************************************************************************/
diff --git a/src/Bpp/Numeric/DataTable.h b/src/Bpp/Numeric/DataTable.h
index b9f55c8..ce30784 100644
--- a/src/Bpp/Numeric/DataTable.h
+++ b/src/Bpp/Numeric/DataTable.h
@@ -41,8 +41,7 @@
#define _DataTable_H_
#include "VectorTools.h"
-#include "DataTableExceptions.h"
-#include "../Exceptions.h"
+#include "TableExceptions.h"
#include "../Text/TextTools.h"
#include "../Clonable.h"
diff --git a/src/Bpp/Numeric/DataTableExceptions.h b/src/Bpp/Numeric/DataTableExceptions.h
deleted file mode 100644
index e06d46d..0000000
--- a/src/Bpp/Numeric/DataTableExceptions.h
+++ /dev/null
@@ -1,175 +0,0 @@
-//
-// File: DataTableExceptions.h
-// Created by: Julien Dutheil
-// Created on: Tue Nov 2005 14:10
-// from file DataTable.h
-//
-
-/*
-Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
-
-This software is a computer program whose purpose is to provide classes
-for numerical calculus.
-
-This software is governed by the CeCILL license under French law and
-abiding by the rules of distribution of free software. You can use,
-modify and/ or redistribute the software under the terms of the CeCILL
-license as circulated by CEA, CNRS and INRIA at the following URL
-"http://www.cecill.info".
-
-As a counterpart to the access to the source code and rights to copy,
-modify and redistribute granted by the license, users are provided only
-with a limited warranty and the software's author, the holder of the
-economic rights, and the successive licensors have only limited
-liability.
-
-In this respect, the user's attention is drawn to the risks associated
-with loading, using, modifying and/or developing or reproducing the
-software by the user in light of its specific status of free software,
-that may mean that it is complicated to manipulate, and that also
-therefore means that it is reserved for developers and experienced
-professionals having in-depth computer knowledge. Users are therefore
-encouraged to load and test the software's suitability as regards their
-requirements in conditions enabling the security of their systems and/or
-data to be ensured and, more generally, to use and operate it in the
-same conditions as regards security.
-
-The fact that you are presently reading this means that you have had
-knowledge of the CeCILL license and that you accept its terms.
-*/
-
-#ifndef _DataTableExceptions_H_
-#define _DataTableExceptions_H_
-
-//#include "VectorTools.h"
-
-// From Utils:
-#include "../Exceptions.h"
-#include "../Text/TextTools.h"
-
-// From the STL:
-#include <string>
-
-namespace bpp
-{
-
-/**
- * @brief Exception thrown when a given name is not found is a DataTable object.
- */
-class TableNameNotFoundException:
- public Exception
-{
- protected:
- std::string _name;
-
- public:
- TableNameNotFoundException(const std::string & text, const std::string & name) :
- Exception("TableNameNotFoundException: " + name + ". " + text), _name(name) {}
- virtual ~TableNameNotFoundException() throw() {}
-
- public:
- std::string getName() const { return _name; }
-};
-
-/**
- * @brief Exception thrown when a given row name is not found is a DataTable object.
- */
-class TableRowNameNotFoundException:
- public TableNameNotFoundException
-{
- public:
- TableRowNameNotFoundException(const std::string & text, const std::string & name) :
- TableNameNotFoundException("TableRowNameNotFoundException: " + name + ". " + text, name) {}
- virtual ~TableRowNameNotFoundException() throw() {}
-};
-
-/**
- * @brief Exception thrown when a given column name is not found is a DataTable object.
- */
-class TableColumnNameNotFoundException:
- public TableNameNotFoundException
-{
- public:
- TableColumnNameNotFoundException(const std::string & text, const std::string & name) :
- TableNameNotFoundException("TableColumnNameNotFoundException: " + name + ". " + text, name) {}
- virtual ~TableColumnNameNotFoundException() throw() {}
-};
-
-/**
- * @brief Exception thrown when trying to retrieve a row by its name
- * and no row names have been specified.
- */
-class NoTableRowNamesException:
- public Exception
-{
- public:
- NoTableRowNamesException(const std::string & text) :
- Exception("NoTableRowNamesException: "+text) {}
- virtual ~NoTableRowNamesException() throw() {}
-};
-
-/**
- * @brief Exception thrown when trying to retrieve a column by its name
- * and no column names have been specified.
- */
-class NoTableColumnNamesException:
- public Exception
-{
- public:
- NoTableColumnNamesException(const std::string & text) :
- Exception("NoTableColumnNamesException: "+text) {}
- virtual ~NoTableColumnNamesException() throw() {}
-};
-
-/**
- * @brief General exception class dealing with row names.
- */
-class TableRowNamesException:
- public Exception
-{
- public:
- TableRowNamesException(const std::string & text) :
- Exception("TableRowNamesException: "+text) {}
- virtual ~TableRowNamesException() throw() {}
-};
-
-/**
- * @brief General exception class dealing with column names.
- */
-class TableColumnNamesException:
- public Exception
-{
- public:
- TableColumnNamesException(const std::string & text) :
- Exception("TableColumnNamesException: "+text) {}
- virtual ~TableColumnNamesException() throw() {}
-};
-
-/**
- * @brief Exception thrown when attempting to duplicate a row name.
- */
-class DuplicatedTableRowNameException:
- public Exception
-{
- public:
- DuplicatedTableRowNameException(const std::string & text) :
- Exception("DuplicatedTableRowNameException: "+text) {}
- virtual ~DuplicatedTableRowNameException() throw() {}
-};
-
-/**
- * @brief Excpetion thrown when attempting to duplicate a column name.
- */
-class DuplicatedTableColumnNameException:
- public Exception
-{
- public:
- DuplicatedTableColumnNameException(const std::string & text) :
- Exception("DuplicatedTableColumnNameException: "+text) {}
- virtual ~DuplicatedTableColumnNameException() throw() {}
-};
-
-} //end of namespace bpp.
-
-#endif //_DataTableExceptions_H_
-
diff --git a/src/Bpp/Numeric/Function/AbstractNumericalDerivative.h b/src/Bpp/Numeric/Function/AbstractNumericalDerivative.h
index c2436f4..70e9b4e 100644
--- a/src/Bpp/Numeric/Function/AbstractNumericalDerivative.h
+++ b/src/Bpp/Numeric/Function/AbstractNumericalDerivative.h
@@ -136,7 +136,7 @@ class AbstractNumericalDerivative:
double getInterval() const { return h_; }
/**
- * @brief Set the list of parameters to derivate.
+ * @brief Set the list of parameters to derivate numerically.
*
* @param variables A list of all parameter names.
*/
@@ -162,17 +162,14 @@ class AbstractNumericalDerivative:
double getFirstOrderDerivative(const std::string& variable) const
throw (Exception)
{
- if (function1_)
- {
- try
- {
- return function1_->getFirstOrderDerivative(variable);
- }
- catch (Exception& e) {}
- }
std::map<std::string, size_t>::iterator it = index_.find(variable);
- if (computeD1_ && it != index_.end()) return der1_[it->second];
- else throw Exception("First order derivative not computed for variable " + variable + ".");
+ if (computeD1_ && it != index_.end())
+ return der1_[it->second];
+
+ if (function1_)
+ return function1_->getFirstOrderDerivative(variable);
+
+ throw Exception("First order derivative not computed for variable " + variable + ".");
}
/** @} */
@@ -188,35 +185,29 @@ class AbstractNumericalDerivative:
double getSecondOrderDerivative(const std::string& variable) const
throw (Exception)
{
- if (function2_)
- {
- try
- {
- return function2_->getSecondOrderDerivative(variable);
- }
- catch(Exception & e) {}
- }
std::map<std::string, size_t>::iterator it = index_.find(variable);
- if(computeD2_ && it != index_.end()) return der2_[it->second];
- else throw Exception("Second order derivative not computed for variable " + variable + ".");
+ if(computeD2_ && it != index_.end())
+ return der2_[it->second];
+
+ if (function2_)
+ return function2_->getSecondOrderDerivative(variable);
+
+ throw Exception("Second order derivative not computed for variable " + variable + ".");
}
double getSecondOrderDerivative(const std::string& variable1, const std::string& variable2) const
throw (Exception)
{
- if (function2_)
- {
- try
- {
- return function2_->getSecondOrderDerivative(variable1, variable2);
- }
- catch(Exception & e) {}
- }
std::map<std::string, size_t>::iterator it1 = index_.find(variable1);
std::map<std::string, size_t>::iterator it2 = index_.find(variable2);
if(computeCrossD2_ && it1 != index_.end() && it2 != index_.end()) return crossDer2_(it1->second, it2->second);
- else throw Exception("Cross second order derivative not computed for variables " + variable1 + " and " + variable2 + ".");
+
+ if (function2_)
+ return function2_->getSecondOrderDerivative(variable1, variable2);
+
+ throw Exception("Cross second order derivative not computed for variables " + variable1 + " and " + variable2 + ".");
}
+
/** @} */
/**
diff --git a/src/Bpp/Numeric/Function/BrentOneDimension.cpp b/src/Bpp/Numeric/Function/BrentOneDimension.cpp
index 6321268..1203ce3 100644
--- a/src/Bpp/Numeric/Function/BrentOneDimension.cpp
+++ b/src/Bpp/Numeric/Function/BrentOneDimension.cpp
@@ -169,7 +169,9 @@ double BrentOneDimension::doStep() throw (Exception)
// Function evaluaton:
ParameterList pl = getParameters();
pl[0].setValue(u);
+
fu = getFunction()->f(pl);
+
if (fu <= fx)
{
if (u >= x) a = x; else b = x;
diff --git a/src/Bpp/Numeric/Function/ConjugateGradientMultiDimensions.cpp b/src/Bpp/Numeric/Function/ConjugateGradientMultiDimensions.cpp
index adc339e..bdfb3aa 100644
--- a/src/Bpp/Numeric/Function/ConjugateGradientMultiDimensions.cpp
+++ b/src/Bpp/Numeric/Function/ConjugateGradientMultiDimensions.cpp
@@ -40,6 +40,8 @@ knowledge of the CeCILL license and that you accept its terms.
#include "ConjugateGradientMultiDimensions.h"
#include "OneDimensionOptimizationTools.h"
+#include "../VectorTools.h"
+
using namespace bpp;
/******************************************************************************/
@@ -81,13 +83,16 @@ double ConjugateGradientMultiDimensions::doStep() throw (Exception)
nbEval_ += OneDimensionOptimizationTools::lineMinimization(f1dim_,
getParameters_(), xi_, getStopCondition()->getTolerance(),
0, 0, getVerbose() > 0 ? getVerbose() - 1 : 0);
+
getFunction_()->enableFirstOrderDerivatives(true);
f = getFunction()->f(getParameters());
+
if (tolIsReached_)
{
return f;
}
getGradient(xi_);
+
dgg = gg = 0.0;
for (unsigned j = 0; j < n; j++)
{
@@ -95,6 +100,7 @@ double ConjugateGradientMultiDimensions::doStep() throw (Exception)
/* dgg += xi[j] * xi[j]; */ //This statement for Fletcher-Reeves.
dgg += (xi_[j] + g_[j]) * xi_[j]; //This statement for Polak-Ribiere.
}
+
if (gg == 0.0)
{
//Unlikely. If gradient is exactly zero then
diff --git a/src/Bpp/Numeric/Function/DownhillSimplexMethod.h b/src/Bpp/Numeric/Function/DownhillSimplexMethod.h
index f9b7671..efb5f3f 100644
--- a/src/Bpp/Numeric/Function/DownhillSimplexMethod.h
+++ b/src/Bpp/Numeric/Function/DownhillSimplexMethod.h
@@ -115,12 +115,7 @@ class DownhillSimplexMethod:
virtual ~DownhillSimplexMethod() {}
-#ifndef NO_VIRTUAL_COV
- DownhillSimplexMethod*
-#else
- Clonable*
-#endif
- clone() const { return new DownhillSimplexMethod(*this); }
+ DownhillSimplexMethod* clone() const { return new DownhillSimplexMethod(*this); }
public:
/**
diff --git a/src/Bpp/Numeric/Function/Functions.h b/src/Bpp/Numeric/Function/Functions.h
index 7c2e790..ed782c7 100644
--- a/src/Bpp/Numeric/Function/Functions.h
+++ b/src/Bpp/Numeric/Function/Functions.h
@@ -129,15 +129,11 @@ class Function:
class DerivableFirstOrder:
public virtual Function
{
- public:
+ public:
DerivableFirstOrder() {}
virtual ~DerivableFirstOrder() {}
-#if defined(NO_VIRTUAL_COV)
- Clonable* clone() const = 0;
-#else
DerivableFirstOrder* clone() const = 0;
-#endif
public:
@@ -193,11 +189,7 @@ class DerivableSecondOrder:
DerivableSecondOrder() {}
virtual ~DerivableSecondOrder() {}
-#if defined(NO_VIRTUAL_COV)
- Clonable* clone() const = 0;
-#else
DerivableSecondOrder* clone() const = 0;
-#endif
public:
@@ -448,11 +440,7 @@ class InfinityFunctionWrapper:
constraintMatch_(false) {}
virtual ~InfinityFunctionWrapper() {}
-#if defined(NO_VIRTUAL_COV)
- Clonable* clone() const { return new InfinityFunctionWrapper(*this); }
-#else
InfinityFunctionWrapper* clone() const { return new InfinityFunctionWrapper(*this); }
-#endif
public:
@@ -553,11 +541,7 @@ class InfinityDerivableFirstOrderWrapper :
InfinityDerivableFirstOrderWrapper(DerivableFirstOrder* function) : InfinityFunctionWrapper(function) {}
virtual ~InfinityDerivableFirstOrderWrapper() {}
-#if defined(NO_VIRTUAL_COV)
- Clonable* clone() const { return new InfinityDerivableFirstOrderWrapper(*this); }
-#else
InfinityDerivableFirstOrderWrapper* clone() const { return new InfinityDerivableFirstOrderWrapper(*this); }
-#endif
public:
@@ -587,11 +571,7 @@ class InfinityDerivableSecondOrderWrapper :
InfinityDerivableFirstOrderWrapper(function) {}
virtual ~InfinityDerivableSecondOrderWrapper() {}
-#if defined(NO_VIRTUAL_COV)
- Clonable* clone() const { return new InfinityDerivableSecondOrderWrapper(*this); }
-#else
InfinityDerivableSecondOrderWrapper* clone() const { return new InfinityDerivableSecondOrderWrapper(*this); }
-#endif
public:
diff --git a/src/Bpp/Numeric/Function/MetaOptimizer.h b/src/Bpp/Numeric/Function/MetaOptimizer.h
index c776911..6c50d70 100644
--- a/src/Bpp/Numeric/Function/MetaOptimizer.h
+++ b/src/Bpp/Numeric/Function/MetaOptimizer.h
@@ -100,11 +100,7 @@ namespace bpp
}
public:
-#ifndef NO_VIRTUAL_COV
MetaOptimizerInfos* clone() const { return new MetaOptimizerInfos(*this); }
-#else
- Clonable* clone() const { return new MetaOptimizerInfos(*this); }
-#endif
public:
/**
diff --git a/src/Bpp/Numeric/Function/OneDimensionOptimizationTools.cpp b/src/Bpp/Numeric/Function/OneDimensionOptimizationTools.cpp
index 238fe64..b11a094 100644
--- a/src/Bpp/Numeric/Function/OneDimensionOptimizationTools.cpp
+++ b/src/Bpp/Numeric/Function/OneDimensionOptimizationTools.cpp
@@ -72,6 +72,13 @@ Bracket OneDimensionOptimizationTools::bracketMinimum(
parameters[0].setValue(bracket.a.x); bracket.a.f = function->f(parameters);
bracket.b.x = b;
parameters[0].setValue(bracket.b.x); bracket.b.f = function->f(parameters);
+
+ while (std::isnan(bracket.b.f)|| std::isinf(bracket.b.f))
+ {
+ bracket.b.x /= 1.1;
+ parameters[0].setValue(bracket.b.x); bracket.b.f = function->f(parameters);
+ }
+
if (bracket.b.f > bracket.a.f)
{
// Switch roles of first and second point so that we can go downhill
@@ -84,6 +91,7 @@ Bracket OneDimensionOptimizationTools::bracketMinimum(
bracket.c.x = bracket.b.x + NumConstants::GOLDEN_RATIO_PHI() * (bracket.b.x - bracket.a.x);
parameters[0].setValue(bracket.c.x); bracket.c.f = function->f(parameters);
+
// Keep returning here until we bracket:
while (bracket.b.f > bracket.c.f)
{
diff --git a/src/Bpp/Numeric/Function/Operators/BinaryOperator.h b/src/Bpp/Numeric/Function/Operators/BinaryOperator.h
new file mode 100644
index 0000000..d1ff67e
--- /dev/null
+++ b/src/Bpp/Numeric/Function/Operators/BinaryOperator.h
@@ -0,0 +1,168 @@
+//
+// File: BinaryOperator.h
+// Created by: Laurent Guéguen
+// Created on: lundi 5 décembre 2016, à 23h 05
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+This software is a computer program whose purpose is to provide classes
+for numerical calculus.
+
+This software is governed by the CeCILL license under French law and
+abiding by the rules of distribution of free software. You can use,
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info".
+
+As a counterpart to the access to the source code and rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty and the software's author, the holder of the
+economic rights, and the successive licensors have only limited
+liability.
+
+In this respect, the user's attention is drawn to the risks associated
+with loading, using, modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean that it is complicated to manipulate, and that also
+therefore means that it is reserved for developers and experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or
+data to be ensured and, more generally, to use and operate it in the
+same conditions as regards security.
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#ifndef _BINARY_OPERATOR_H_
+#define _BINARY_OPERATOR_H_
+
+#include <memory>
+
+namespace bpp
+{
+
+/**
+ * @brief Binary arithmetic operator for numerical computation.
+ *
+ */
+
+ class BinaryOperator:
+ public Operator
+ {
+ private:
+ char symb_;
+
+ std::shared_ptr<Operator> left_, right_;
+
+ public:
+
+ BinaryOperator(char symb, std::shared_ptr<Operator> left, std::shared_ptr<Operator> right) :
+ symb_(symb), left_(left), right_(right)
+ {
+ }
+
+ BinaryOperator* clone() const
+ {
+ return new BinaryOperator(*this);
+ }
+
+ char getSymbol() const
+ {
+ return symb_;
+ }
+
+ double getValue() const
+ {
+ switch(symb_)
+ {
+ case '+':
+ return left_->getValue() + right_->getValue();
+ case '-':
+ return left_->getValue() - right_->getValue();
+ case '/':
+ if (right_->getValue()==0)
+ return 0;
+
+ return left_->getValue() / right_->getValue();
+ case '*':
+ return left_->getValue() * right_->getValue();
+ default:
+ return 0;
+ }
+ }
+
+ double getFirstOrderDerivative(const std::string& variable) const
+ {
+ double dl = left_->getFirstOrderDerivative(variable);
+ double dr = right_->getFirstOrderDerivative(variable);
+ double l = left_->getValue();
+ double r = right_->getValue();
+
+ switch(symb_)
+ {
+ case '+':
+ return dl + dr;
+ case '-':
+ return dl - dl;
+ case '/':
+ if (r==0)
+ return 0;
+
+ return (dl * r - dr * l ) / (r * r);
+ case '*':
+ return dl * r + dr * l;
+ default:
+ return 0;
+ }
+ return 0;
+ }
+
+ double getSecondOrderDerivative(const std::string& variable) const
+ {
+ double d2l = left_->getSecondOrderDerivative(variable);
+ double d2r = right_->getSecondOrderDerivative(variable);
+ double l = left_->getValue();
+ double r = right_->getValue();
+ double dl = left_->getFirstOrderDerivative(variable);
+ double dr = right_->getFirstOrderDerivative(variable);
+
+ double r2 = r*r;
+ double r3 = r*r2;
+
+ switch(symb_)
+ {
+ case '+':
+ return d2l + d2r;
+ case '-':
+ return d2l - d2r;
+
+ case '/':
+ if (r==0)
+ return 0;
+
+ return (d2l * r - d2r * l ) / r2 - ( 2 * dl * ( dl * r - dr * l) ) / r3;
+
+ case '*':
+ return d2l * r + d2r * l + 2 * dr * dl;
+ default:
+ return 0;
+ }
+ }
+
+ std::string output() const
+ {
+ return "(" + left_->output() + " " + symb_ + " " + right_->output() + ")";
+ }
+
+
+ };
+
+
+} //end of namespace bpp.
+
+#endif //_BINARY_OPERATOR_H_
+
diff --git a/src/Bpp/Numeric/Function/Operators/ComputationTree.cpp b/src/Bpp/Numeric/Function/Operators/ComputationTree.cpp
new file mode 100644
index 0000000..368106f
--- /dev/null
+++ b/src/Bpp/Numeric/Function/Operators/ComputationTree.cpp
@@ -0,0 +1,213 @@
+//
+// File: ComputationTree.cpp
+// Created by: Laurent Guéguen
+// Created on: mardi 6 décembre 2016, à 00h 07
+//
+
+/*
+ Copyright or © or Copr. CNRS, (November 16, 2004)
+
+ This software is a computer program whose purpose is to provide classes
+ for phylogenetic data analysis.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#include "ComputationTree.h"
+
+#include "BinaryOperator.h"
+#include "FunctionOperator.h"
+#include "ConstantOperator.h"
+#include "MathOperator.h"
+
+#include <algorithm>
+
+using namespace std;
+using namespace bpp;
+
+ComputationTree::ComputationTree(const std::string& formula, const std::map<std::string, Function*>& functionNames):
+ AssociationTreeGlobalGraphObserver<Operator,short>(true)
+{
+ getGraph() ;
+
+ std::string str2 = formula;
+
+ str2.erase(std::remove_if(str2.begin(),
+ str2.end(),
+ [](char x){return std::isspace(x);}),
+ str2.end());
+
+ setRoot(readFormula_(str2, functionNames));
+}
+
+std::shared_ptr<Operator> ComputationTree::readFormula_(const std::string& formula, const std::map<std::string, Function*>& functionNames)
+{
+ unsigned int level = 0;
+ //inside parentheses check
+ //case + or -
+ //most right '+' or '-' (but not inside '()') search and split
+
+ for(size_t i=formula.size();i>0;--i){
+
+ char c = formula[i-1];
+
+ if(c == ')'){
+ ++level;
+ continue;
+ }
+
+ if(c == '('){
+ --level;
+ continue;
+ }
+
+ if(level>0)
+ continue;
+
+ if ((c == '+' || c == '-') && !(i==1 || formula[i-2] == '*' || formula[i-2] == '/'
+ || formula[i-2] == '+' || formula[i-2] == '-'))
+ {
+
+ //if sign
+
+ std::shared_ptr<Operator> left=readFormula_(formula.substr(0,i-1), functionNames);
+ std::shared_ptr<Operator> right=readFormula_(formula.substr(i), functionNames);
+
+ shared_ptr<Operator> here(new BinaryOperator(c,left,right));
+
+ createNode(here);
+
+ setFather(left, here);
+ setFather(right, here);
+
+ return here;
+ }
+ }
+
+ //case * or /
+ //most right '*' or '/' (but not inside '()') search and split
+ for(size_t i=formula.size();i>0;--i){
+
+ char c = formula[i-1];
+
+ if(c == ')'){
+ ++level;
+ continue;
+ }
+
+ if(c == '('){
+ --level;
+ continue;
+ }
+
+ if(level>0)
+ continue;
+
+ if(c == '*' || c == '/'){
+
+ std::shared_ptr<Operator> left=readFormula_(formula.substr(0,i-1), functionNames);
+ std::shared_ptr<Operator> right=readFormula_(formula.substr(i), functionNames);
+
+ shared_ptr<Operator> here(new BinaryOperator(c,left,right));
+
+ createNode(here);
+
+ setFather(left, here);
+ setFather(right, here);
+
+ return here;
+ }
+
+ }
+
+
+ if(formula[0]=='(')
+ return readFormula_(formula.substr(1, formula.size()-2), functionNames);
+
+ else
+ //case value
+ {
+ shared_ptr<Operator> here;
+ try
+ {
+ double v = TextTools::toDouble(formula);
+ here = shared_ptr<Operator>(new ConstantOperator(v));
+ }
+ catch (Exception e)
+ {
+ std::map<std::string, Function*>::const_iterator it(functionNames.find(formula));
+
+ if (it!=functionNames.end())
+ {
+ if (dynamic_cast<const DerivableSecondOrder*>(it->second))
+ here=shared_ptr<Operator>(new FunctionOperator<DerivableSecondOrder>(*dynamic_cast<DerivableSecondOrder*>(it->second),formula));
+ else
+ if (dynamic_cast<const DerivableFirstOrder*>(it->second))
+ here=shared_ptr<Operator>(new FunctionOperator<DerivableFirstOrder>(*dynamic_cast<DerivableFirstOrder*>(it->second),formula));
+ else
+ here=shared_ptr<Operator>(new FunctionOperator<Function>(*it->second,formula));
+ }
+ else
+ {
+ size_t posp=formula.find("(");
+ if (posp==string::npos)
+ throw Exception("ComputationTree::readFormula_ : unknown formula : "+ formula);
+
+ std::shared_ptr<Operator> son=readFormula_(formula.substr(posp), functionNames);
+ string fonc=formula.substr(0,posp);
+
+ if (fonc=="exp")
+ here=shared_ptr<Operator>(new MathOperator(&exp,"exp",son));
+ else if (fonc=="log")
+ here=shared_ptr<Operator>(new MathOperator(&log,"log",son));
+ else
+ throw Exception("ComputationTree::readFormula_ : unknown formula : "+ formula);
+ }
+ }
+
+ this->getGraph();
+ createNode(here);
+ return here;
+ }
+
+ return NULL;
+ //never
+}
+
+bool ComputationTree::isAllSum()
+{
+ std::unique_ptr<NodeIterator> it=allNodesIterator();
+
+ for (;it->end();it->next())
+ {
+ const BinaryOperator* op = dynamic_cast<const BinaryOperator*>((**it).get());
+ if (op && op->getSymbol()!='+' && op->getSymbol()!='-')
+ return false;
+ }
+ return true;
+
+}
diff --git a/src/Bpp/Numeric/Function/Operators/ComputationTree.h b/src/Bpp/Numeric/Function/Operators/ComputationTree.h
new file mode 100644
index 0000000..38ed7ac
--- /dev/null
+++ b/src/Bpp/Numeric/Function/Operators/ComputationTree.h
@@ -0,0 +1,113 @@
+//
+// File: ComputationTree.h
+// Created by: Laurent Guéguen
+// Created on: mardi 6 décembre 2016, à 00h 07
+//
+
+/*
+ Copyright or © or Copr. CNRS, (November 16, 2004)
+
+ This software is a computer program whose purpose is to provide classes
+ for phylogenetic data analysis.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#ifndef _COMPUTATION_TREE_H_
+#define _COMPUTATION_TREE_H_
+
+#include "../../../Graph/AssociationTreeGraphImplObserver.h"
+
+#include "Operator.h"
+#include "../Functions.h"
+#include <memory>
+
+namespace bpp
+{
+/**
+ * @brief Defines a Computation Tree based on Operators.
+ *
+ */
+
+ class ComputationTree:
+ public AssociationTreeGlobalGraphObserver<Operator,short>
+ {
+ private:
+ std::shared_ptr<Operator> readFormula_(const std::string& formula,const std::map<std::string, Function*>& functionNames);
+
+ public:
+ /*
+ * @brief Tree for numerical computation given a formula (such as
+ * 2*f+g), and given a map from function name (f) to real
+ * function.
+ *
+ */
+
+ ComputationTree(const std::string& formula, const std::map<std::string, Function*>& functionNames);
+
+ ComputationTree* clone() const
+ {
+ return new ComputationTree(*this);
+ }
+
+ double getValue() const
+ {
+ return getRoot()->getValue();
+ }
+
+ double getFirstOrderDerivative(const std::string& variable) const
+ {
+ return getRoot()->getFirstOrderDerivative(variable);
+ }
+
+ double getSecondOrderDerivative(const std::string& variable) const
+ {
+ return getRoot()->getSecondOrderDerivative(variable);
+ }
+
+ void readFormula(const std::string& formula,const std::map<std::string, Function*>& functionNames)
+ {
+ readFormula_(formula, functionNames);
+ }
+
+ std::string output() const
+ {
+ return getRoot()->output();
+ }
+
+ /*
+ * Return true if all binary operators are '+' or '-'
+ *
+ */
+
+ bool isAllSum();
+
+ };
+
+}
+
+#endif
diff --git a/src/Bpp/BppBoolean.h b/src/Bpp/Numeric/Function/Operators/ConstantOperator.h
similarity index 63%
copy from src/Bpp/BppBoolean.h
copy to src/Bpp/Numeric/Function/Operators/ConstantOperator.h
index 25041ea..df954b1 100644
--- a/src/Bpp/BppBoolean.h
+++ b/src/Bpp/Numeric/Function/Operators/ConstantOperator.h
@@ -1,14 +1,14 @@
//
-// File: BppBoolean.h
-// Created by: Julien Dutheil
-// Created on: Fri 31 10:44 2010
+// File: ConstantOperator.h
+// Created by: Laurent Guéguen
+// Created on: lundi 5 décembre 2016, à 23h 21
//
/*
Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
-This software is a computer program whose purpose is to provide utilitary
-classes. This file belongs to the Bio++ Project.
+This software is a computer program whose purpose is to provide classes
+for numerical calculus.
This software is governed by the CeCILL license under French law and
abiding by the rules of distribution of free software. You can use,
@@ -37,58 +37,60 @@ The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms.
*/
-#ifndef _BPP_BOOLEAN_H_
-#define _BPP_BOOLEAN_H_
+#ifndef _CONSTANT_OPERATOR_H_
+#define _CONSTANT_OPERATOR_H_
-#include "Clonable.h"
-
-// From the STL:
-#include <string>
-#include <ostream>
+#include <memory>
+#include "../../../Text/TextTools.h"
namespace bpp
{
/**
- * @brief The BppBoolean object class.
+ * @brief Constant (ie leaf) operator.
*
- * This class extends the bool type to support the Clonable interface.
*/
-class BppBoolean: public virtual Clonable
-{
+
+ class ConstantOperator:
+ public Operator
+ {
private:
- bool value_;
-
- public:
-
- BppBoolean(): value_(false) {}
- BppBoolean(bool value): value_(value) {}
- virtual ~BppBoolean() {}
-
- public:
-
- /**
- * @name The Clonable interface.
- *
- * @{
- */
-#ifdef NO_VIRTUAL_COV
- Clonable*
-#else
- BppBoolean*
-#endif
- clone() const { return new BppBoolean(*this); }
- /** @} */
-
- const bool getValue() const { return value_; }
+ const double value_;
-};
+ public:
+
+ ConstantOperator(double value) :
+ value_(value) {}
-std::ostream& operator<<(std::ostream& out, const BppBoolean& s) {
- return out << s.getValue();
-}
+ ConstantOperator* clone() const
+ {
+ return new ConstantOperator(*this);
+ }
+
+ double getValue() const
+ {
+ return value_;
+ }
+
+ double getFirstOrderDerivative(const std::string& variable) const
+ {
+ return 0;
+ }
+
+ double getSecondOrderDerivative(const std::string& variable) const
+ {
+ return 0;
+ }
+
+ std::string output() const
+ {
+ return TextTools::toString(value_);
+ }
+
+ };
+
} //end of namespace bpp.
-#endif //_BPP_BOOLEAN_H_
+#endif //_CONSTANT_OPERATOR_H_
diff --git a/src/Bpp/Numeric/Function/Operators/FunctionOperator.h b/src/Bpp/Numeric/Function/Operators/FunctionOperator.h
new file mode 100644
index 0000000..a97614d
--- /dev/null
+++ b/src/Bpp/Numeric/Function/Operators/FunctionOperator.h
@@ -0,0 +1,133 @@
+//
+// File: FunctionOperator.h
+// Created by: Laurent Guéguen
+// Created on: lundi 5 décembre 2016, à 23h 05
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+This software is a computer program whose purpose is to provide classes
+for numerical calculus.
+
+This software is governed by the CeCILL license under French law and
+abiding by the rules of distribution of free software. You can use,
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info".
+
+As a counterpart to the access to the source code and rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty and the software's author, the holder of the
+economic rights, and the successive licensors have only limited
+liability.
+
+In this respect, the user's attention is drawn to the risks associated
+with loading, using, modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean that it is complicated to manipulate, and that also
+therefore means that it is reserved for developers and experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or
+data to be ensured and, more generally, to use and operate it in the
+same conditions as regards security.
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#ifndef _FUNCTION_OPERATOR_H_
+#define _FUNCTION_OPERATOR_H_
+
+#include <memory>
+#include "../Functions.h"
+
+namespace bpp
+{
+
+/**
+ * @brief Implements a double operator (ie leaf in the computation
+ * tree) where value comes from a function.
+ *
+ */
+
+ template<class F>
+ class FunctionOperator:
+ public Operator
+ {
+ private:
+ F& func_;
+
+ std::string name_;
+
+ double getValue_(std::true_type) const
+ {
+ return func_.getValue();
+ }
+
+ double getValue_(std::false_type) const
+ {
+ return 0;
+ }
+
+ double getFirstOrderDerivative_(const std::string& variable, std::true_type) const
+ {
+ return func_.getFirstOrderDerivative(variable);
+ }
+
+ double getFirstOrderDerivative_(const std::string& variable, std::false_type) const
+ {
+ return 0;
+ }
+
+ double getSecondOrderDerivative_(const std::string& variable, std::true_type) const
+ {
+ return func_.getSecondOrderDerivative(variable);
+ }
+
+ double getSecondOrderDerivative_(const std::string& variable, std::false_type) const
+ {
+ return 0;
+ }
+
+
+ public:
+
+ FunctionOperator(F& func, std::string name) :
+ func_(func), name_(name)
+ {
+ }
+
+ FunctionOperator* clone() const
+ {
+ return new FunctionOperator(*this);
+ }
+
+ double getValue() const
+ {
+ return getValue_(std::integral_constant<bool, std::is_base_of<Function, F>::value>{});
+ }
+
+ double getFirstOrderDerivative(const std::string& variable) const
+ {
+ return getFirstOrderDerivative_(variable, std::integral_constant<bool, std::is_base_of<DerivableFirstOrder, F>::value>{});
+ }
+
+ double getSecondOrderDerivative(const std::string& variable) const
+ {
+ return getSecondOrderDerivative_(variable, std::integral_constant<bool, std::is_base_of<DerivableSecondOrder, F>::value>{});
+ }
+
+ std::string output() const
+ {
+ return name_;
+ }
+
+ };
+
+
+} //end of namespace bpp.
+
+#endif //_FUNCTION_OPERATOR_H_
+
diff --git a/src/Bpp/Numeric/Function/Operators/MathOperator.h b/src/Bpp/Numeric/Function/Operators/MathOperator.h
new file mode 100644
index 0000000..0fa05be
--- /dev/null
+++ b/src/Bpp/Numeric/Function/Operators/MathOperator.h
@@ -0,0 +1,138 @@
+//
+// File: MathOperator.h
+// Created by: Laurent Guéguen
+// Created on: lundi 5 décembre 2016, à 23h 05
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+This software is a computer program whose purpose is to provide classes
+for numerical calculus.
+
+This software is governed by the CeCILL license under French law and
+abiding by the rules of distribution of free software. You can use,
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info".
+
+As a counterpart to the access to the source code and rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty and the software's author, the holder of the
+economic rights, and the successive licensors have only limited
+liability.
+
+In this respect, the user's attention is drawn to the risks associated
+with loading, using, modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean that it is complicated to manipulate, and that also
+therefore means that it is reserved for developers and experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or
+data to be ensured and, more generally, to use and operate it in the
+same conditions as regards security.
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#ifndef _MATH_OPERATOR_H_
+#define _MATH_OPERATOR_H_
+
+#include <memory>
+#include <cmath>
+
+namespace bpp
+{
+
+/**
+ * @brief Implements a unary operator that applies a math (described
+ * in cmath) operator.
+ *
+ */
+
+ class MathOperator:
+ public Operator
+ {
+ private:
+ /*
+ * @brief pointer to function.
+ * If null, identity function is used.
+ */
+
+ double (*func_)(double);
+
+ std::string name_;
+
+ std::shared_ptr<Operator> son_;
+
+ public:
+
+ MathOperator(double (*func)(double), std::string name, std::shared_ptr<Operator> son) :
+ func_(func), name_(name), son_(son)
+ {
+ }
+
+ MathOperator* clone() const
+ {
+ return new MathOperator(*this);
+ }
+
+
+ double getValue() const
+ {
+ if (func_)
+ return (*func_)(son_->getValue());
+ else
+ return son_->getValue();
+ }
+
+ /**
+ * @brief 1st order derivative
+ *
+ */
+
+ double getFirstOrderDerivative(const std::string& variable) const
+ {
+ double v = son_->getValue();
+ double d = son_->getFirstOrderDerivative(variable);
+
+ if (name_=="exp")
+ return d*exp(v);
+ else if (name_=="log")
+ return d/v;
+ else
+ throw Exception("MathOperator::getFirstOrderDerivative : unknown function " + name_);
+
+ }
+
+ double getSecondOrderDerivative(const std::string& variable) const
+ {
+ double v = son_->getValue();
+ double d = son_->getFirstOrderDerivative(variable);
+ double d2 = son_->getSecondOrderDerivative(variable);
+
+ if (name_=="exp")
+ return (d2+d*d)*exp(v);
+ else if (name_=="log")
+ return (d2*v-d*d)/(v*v);
+ else
+ throw Exception("MathOperator::getFirstOrderDerivative : unknown function " + name_);
+ return 0;
+ }
+
+
+ std::string output() const
+ {
+ return name_ + "(" + son_->output() + ")";
+ }
+
+
+ };
+
+
+} //end of namespace bpp.
+
+#endif //_MATH_OPERATOR_H_
+
diff --git a/src/Bpp/Graph/BasicONode.h b/src/Bpp/Numeric/Function/Operators/Operator.h
similarity index 65%
rename from src/Bpp/Graph/BasicONode.h
rename to src/Bpp/Numeric/Function/Operators/Operator.h
index 2cf8bfb..7151ef1 100644
--- a/src/Bpp/Graph/BasicONode.h
+++ b/src/Bpp/Numeric/Function/Operators/Operator.h
@@ -1,14 +1,14 @@
-//
-// File: BasicONode.h
-// Author: Sylvain Gaillard
-// Created: 13/01/2011 16:34:44
-//
+//
+// File: Operator.h
+// Created by: Laurent Guéguen
+// Created on: lundi 5 décembre 2016, à 23h 02
+//
/*
-Copyright or © or Copr. Bio++ Development Team, (January 12, 2011)
+Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
-This software is a computer program whose purpose is to provide utilitary
-classes. This file belongs to the Bio++ Project.
+This software is a computer program whose purpose is to provide classes
+for numerical calculus.
This software is governed by the CeCILL license under French law and
abiding by the rules of distribution of free software. You can use,
@@ -37,25 +37,37 @@ The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms.
*/
-#ifndef _BPP_GRAPH_BASICONODE_H_
-#define _BPP_GRAPH_BASICONODE_H_
-
-#include "ONode.h"
-
-namespace bpp {
- /**
- * @brief Simple implementation of ONode
- *
- * Contains only methods for node manipulation.
- *
- * @warning Class not implemented yet!
- *
- * @author Sylvain Gaillard
- */
- class BasicONode: public ONode {
- public:
- BasicONode();
+#ifndef _OPERATOR_H_
+#define _OPERATOR_H_
+
+#include "../../../Clonable.h"
+
+namespace bpp
+{
+
+/**
+ * @brief Interface of operator for numerical computation.
+ *
+ */
+
+ class Operator :
+ public virtual Clonable
+ {
+ public:
+ virtual ~Operator() {};
+
+ virtual double getValue() const = 0;
+
+ virtual double getFirstOrderDerivative(const std::string& variable) const = 0;
+
+ virtual double getSecondOrderDerivative(const std::string& variable) const = 0;
+
+ virtual std::string output() const = 0;
+
};
-}
+
+
+} //end of namespace bpp.
+
+#endif //_OPERATOR_H_
-#endif //_BPP_GRAPH_BASICONODE_H_
diff --git a/src/Bpp/Numeric/Function/OptimizationStopCondition.h b/src/Bpp/Numeric/Function/OptimizationStopCondition.h
index 3501205..9e0cf50 100644
--- a/src/Bpp/Numeric/Function/OptimizationStopCondition.h
+++ b/src/Bpp/Numeric/Function/OptimizationStopCondition.h
@@ -71,12 +71,7 @@ namespace bpp
OptimizationStopCondition() {}
virtual ~OptimizationStopCondition() {}
-#ifndef NO_VIRTUAL_COV
- OptimizationStopCondition *
-#else
- Clonable*
-#endif
- clone() const = 0;
+ OptimizationStopCondition * clone() const = 0;
public:
@@ -293,12 +288,7 @@ namespace bpp
virtual ~FunctionStopCondition();
-#ifndef NO_VIRTUAL_COV
- FunctionStopCondition*
-#else
- Clonable*
-#endif
- clone() const { return new FunctionStopCondition(*this); }
+ FunctionStopCondition* clone() const { return new FunctionStopCondition(*this); }
public:
void init();
diff --git a/src/Bpp/Numeric/Function/Optimizer.h b/src/Bpp/Numeric/Function/Optimizer.h
index 2231bad..61278a1 100644
--- a/src/Bpp/Numeric/Function/Optimizer.h
+++ b/src/Bpp/Numeric/Function/Optimizer.h
@@ -129,11 +129,7 @@ namespace bpp
Optimizer() {}
virtual ~Optimizer() {}
-#if defined(NO_VIRTUAL_COV)
- Clonable* clone() const = 0;
-#else
Optimizer* clone() const = 0;
-#endif
public:
diff --git a/src/Bpp/Numeric/Function/ReparametrizationFunctionWrapper.h b/src/Bpp/Numeric/Function/ReparametrizationFunctionWrapper.h
index 323b794..05d9f96 100644
--- a/src/Bpp/Numeric/Function/ReparametrizationFunctionWrapper.h
+++ b/src/Bpp/Numeric/Function/ReparametrizationFunctionWrapper.h
@@ -107,11 +107,7 @@ class ReparametrizationFunctionWrapper:
virtual ~ReparametrizationFunctionWrapper() {}
-#if defined(NO_VIRTUAL_COV)
- Clonable* clone() const { return new ReparametrizationFunctionWrapper(*this); }
-#else
ReparametrizationFunctionWrapper* clone() const { return new ReparametrizationFunctionWrapper(*this); }
-#endif
private:
void init_(bool verbose);
@@ -177,11 +173,7 @@ class ReparametrizationDerivableFirstOrderWrapper:
virtual ~ReparametrizationDerivableFirstOrderWrapper() {}
-#if defined(NO_VIRTUAL_COV)
- Clonable* clone() const { return new ReparametrizationDerivableFirstOrderWrapper(*this); }
-#else
ReparametrizationDerivableFirstOrderWrapper* clone() const { return new ReparametrizationDerivableFirstOrderWrapper(*this); }
-#endif
private:
void init_(bool verbose);
@@ -237,11 +229,7 @@ class ReparametrizationDerivableSecondOrderWrapper:
virtual ~ReparametrizationDerivableSecondOrderWrapper() {}
-#if defined(NO_VIRTUAL_COV)
- Clonable* clone() const { return new ReparametrizationDerivableSecondOrderWrapper(*this); }
-#else
ReparametrizationDerivableSecondOrderWrapper* clone() const { return new ReparametrizationDerivableSecondOrderWrapper(*this); }
-#endif
private:
void init_(bool verbose);
diff --git a/src/Bpp/Numeric/Function/ThreePointsNumericalDerivative.cpp b/src/Bpp/Numeric/Function/ThreePointsNumericalDerivative.cpp
index 341864c..64dfe03 100644
--- a/src/Bpp/Numeric/Function/ThreePointsNumericalDerivative.cpp
+++ b/src/Bpp/Numeric/Function/ThreePointsNumericalDerivative.cpp
@@ -53,7 +53,7 @@ throw (ParameterNotFoundException, ConstraintException)
function2_->enableSecondOrderDerivatives(false);
function_->setParameters(parameters);
f2_ = function_->getValue();
- if ((abs(f2_) >= NumConstants::VERY_BIG()) || isnan(f2_))
+ if ((abs(f2_) >= NumConstants::VERY_BIG()) || std::isnan(f2_))
{
for (size_t i = 0; i < variables_.size(); ++i)
{
@@ -103,7 +103,7 @@ throw (ParameterNotFoundException, ConstraintException)
p = p.subList(0);
f1_ = function_->getValue();
- if ((abs(f1_) >= NumConstants::VERY_BIG()) || isnan(f1_))
+ if ((abs(f1_) >= NumConstants::VERY_BIG()) || std::isnan(f1_))
throw ConstraintException("f1_ too large", &p[0], f1_);
else
hf1 = h;
@@ -137,7 +137,7 @@ throw (ParameterNotFoundException, ConstraintException)
p = p.subList(0);
f3_ = function_->getValue();
- if ((abs(f3_) >= NumConstants::VERY_BIG()) || isnan(f3_))
+ if ((abs(f3_) >= NumConstants::VERY_BIG()) || std::isnan(f3_))
throw ConstraintException("f3_ too large", &p[0], f3_);
else
hf3 = h;
diff --git a/src/Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.cpp b/src/Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.cpp
index 8362d12..028f7df 100644
--- a/src/Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.cpp
+++ b/src/Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.cpp
@@ -41,6 +41,7 @@ knowledge of the CeCILL license and that you accept its terms.
#include "../Matrix/MatrixTools.h"
#include "../VectorTools.h"
+#include "../Random/RandomTools.h"
using namespace bpp;
using namespace std;
@@ -82,3 +83,47 @@ void AbstractHmmTransitionMatrix::setHmmStateAlphabet(const HmmStateAlphabet* st
alph_=stateAlphabet;
}
+vector<size_t> AbstractHmmTransitionMatrix::sample(size_t size) const
+{
+ vector<size_t> vres;
+ if (size==0)
+ return vres;
+
+ size_t nbStates=getHmmStateAlphabet()->getNumberOfStates();
+
+ // update pij_
+ getPij();
+
+ size_t sta=0, stb;
+ double prob = RandomTools::giveRandomNumberBetweenZeroAndEntry(1.0);
+
+ for (size_t i = 0; i < nbStates; ++i) {
+ prob-=eqFreq_[i];
+ if (prob < 0) {
+ sta=i;
+ break;
+ }
+ }
+
+ vres.push_back(sta);
+
+ for (size_t pos=1;pos<size;pos++)
+ {
+ prob = RandomTools::giveRandomNumberBetweenZeroAndEntry(1.0);
+
+ const vector<double>& row=pij_.getRow(sta);
+
+ for (size_t i = 0; i < nbStates; ++i) {
+ prob-=row[i];
+ if (prob < 0) {
+ stb=i;
+ break;
+ }
+ }
+ vres.push_back(stb);
+ sta=stb;
+ }
+ return vres;
+}
+
+
diff --git a/src/Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.h b/src/Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.h
index 9e6dee3..c850cf4 100644
--- a/src/Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.h
+++ b/src/Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.h
@@ -100,6 +100,18 @@ public:
return alph_->getNumberOfStates();
}
+ /**
+ * @brief sampling of a sequence of states. Starting point is
+ * sampled from the equilibrium distribution.
+ *
+ * @param size the length of the sequence
+ * @return a vector of states index sampled from the Transition
+ * probabilities
+ *
+ */
+
+ std::vector<size_t> sample(size_t size) const;
+
};
} //end of namespace bpp
diff --git a/src/Bpp/Numeric/Hmm/AutoCorrelationTransitionMatrix.cpp b/src/Bpp/Numeric/Hmm/AutoCorrelationTransitionMatrix.cpp
index 134eeb3..48c071f 100644
--- a/src/Bpp/Numeric/Hmm/AutoCorrelationTransitionMatrix.cpp
+++ b/src/Bpp/Numeric/Hmm/AutoCorrelationTransitionMatrix.cpp
@@ -57,7 +57,7 @@ AutoCorrelationTransitionMatrix::AutoCorrelationTransitionMatrix(const HmmStateA
for (size_t i=0; i<size; i++)
{
vAutocorrel_.push_back(1./(double)size);
- addParameter_(new Parameter("lambda"+TextTools::toString(i+1), 1./(double)size, &Parameter::PROP_CONSTRAINT_EX));
+ addParameter_(new Parameter(prefix + "lambda"+TextTools::toString(i+1), 1./(double)size, &Parameter::PROP_CONSTRAINT_EX));
}
for (size_t i = 0; i < size; i++)
diff --git a/src/Bpp/Numeric/Hmm/FullHmmTransitionMatrix.cpp b/src/Bpp/Numeric/Hmm/FullHmmTransitionMatrix.cpp
index 23f057c..cff06d3 100644
--- a/src/Bpp/Numeric/Hmm/FullHmmTransitionMatrix.cpp
+++ b/src/Bpp/Numeric/Hmm/FullHmmTransitionMatrix.cpp
@@ -56,14 +56,8 @@ FullHmmTransitionMatrix::FullHmmTransitionMatrix(const HmmStateAlphabet* alph, c
for (size_t i=0; i<size; i++)
{
- vSimplex_.push_back(Simplex(size,1));
- ParameterList pl=vSimplex_[i].getParameters();
- for (size_t j=0; j<pl.size(); j++)
- {
- Parameter* p=pl[j].clone();
- p->setName(TextTools::toString(i+1)+"."+p->getName());
- addParameter_(p);
- }
+ vSimplex_.push_back(Simplex(size,1,false,prefix + TextTools::toString(i+1)+"."));
+ addParameters_(vSimplex_[i].getParameters());
}
}
@@ -140,14 +134,7 @@ void FullHmmTransitionMatrix::fireParameterChanged(const ParameterList& paramete
size_t salph=getNumberOfStates();
for (size_t i=0; i< salph; i++)
- {
- ParameterList pl=vSimplex_[i].getParameters();
-
- for (size_t j=0; j<pl.size(); j++)
- pl[j].setValue(getParameterValue(TextTools::toString(i+1)+"."+pl[j].getName()));
-
- vSimplex_[i].matchParametersValues(pl);
- }
+ vSimplex_[i].matchParametersValues(parameters);
upToDate_=false;
}
diff --git a/src/Bpp/Numeric/Hmm/HmmLikelihood.h b/src/Bpp/Numeric/Hmm/HmmLikelihood.h
index 7306ecc..08c9189 100644
--- a/src/Bpp/Numeric/Hmm/HmmLikelihood.h
+++ b/src/Bpp/Numeric/Hmm/HmmLikelihood.h
@@ -79,9 +79,7 @@ namespace bpp
{
public:
-#ifndef NO_VIRTUAL_COV
virtual HmmLikelihood* clone() const = 0;
-#endif
virtual const HmmStateAlphabet& getHmmStateAlphabet() const = 0;
virtual HmmStateAlphabet& getHmmStateAlphabet() = 0;
@@ -102,8 +100,8 @@ namespace bpp
virtual double getD2LogLikelihood() const = 0;
- /**
- * @brief Get the likelihood for a site.
+ /**
+ * @brief Get the likelihood for a site, and its derivatives.
*
* @param site The site index to analyse.
* @return The likelihood for site <i>site</i>.
@@ -111,6 +109,9 @@ namespace bpp
virtual double getLikelihoodForASite(size_t site) const = 0;
+ virtual double getDLogLikelihoodForASite(size_t site) const = 0;
+
+ virtual double getD2LogLikelihoodForASite(size_t site) const = 0;
/**
* @brief Get the likelihood for each site.
*
diff --git a/src/Bpp/Numeric/Hmm/LogsumHmmLikelihood.cpp b/src/Bpp/Numeric/Hmm/LogsumHmmLikelihood.cpp
index 3540f34..423755b 100644
--- a/src/Bpp/Numeric/Hmm/LogsumHmmLikelihood.cpp
+++ b/src/Bpp/Numeric/Hmm/LogsumHmmLikelihood.cpp
@@ -49,12 +49,14 @@ LogsumHmmLikelihood::LogsumHmmLikelihood(
HmmStateAlphabet* hiddenAlphabet,
HmmTransitionMatrix* transitionMatrix,
HmmEmissionProbabilities* emissionProbabilities,
+ bool ownsPointers,
const std::string& prefix) throw (Exception):
AbstractHmmLikelihood(),
AbstractParametrizable(prefix),
hiddenAlphabet_(hiddenAlphabet),
transitionMatrix_(transitionMatrix),
emissionProbabilities_(emissionProbabilities),
+ ownsPointers_(ownsPointers),
logLikelihood_(),
partialLogLikelihoods_(),
logLik_(),
@@ -71,9 +73,10 @@ LogsumHmmLikelihood::LogsumHmmLikelihood(
if (!hiddenAlphabet) throw Exception("LogsumHmmLikelihood: null pointer passed for HmmStateAlphabet.");
if (!transitionMatrix) throw Exception("LogsumHmmLikelihood: null pointer passed for HmmTransitionMatrix.");
if (!emissionProbabilities) throw Exception("LogsumHmmLikelihood: null pointer passed for HmmEmissionProbabilities.");
- if (!hiddenAlphabet_->worksWith(transitionMatrix->getHmmStateAlphabet()))
+
+ if (!hiddenAlphabet_->worksWith(transitionMatrix_->getHmmStateAlphabet()))
throw Exception("LogsumHmmLikelihood: HmmTransitionMatrix and HmmEmissionProbabilities should point toward the same HmmStateAlphabet object.");
- if (!hiddenAlphabet_->worksWith(emissionProbabilities->getHmmStateAlphabet()))
+ if (!hiddenAlphabet_->worksWith(emissionProbabilities_->getHmmStateAlphabet()))
throw Exception("LogsumHmmLikelihood: HmmTransitionMatrix and HmmEmissionProbabilities should point toward the same HmmStateAlphabet object.");
nbStates_ = hiddenAlphabet_->getNumberOfStates();
nbSites_ = emissionProbabilities_->getNumberOfPositions();
@@ -85,11 +88,20 @@ LogsumHmmLikelihood::LogsumHmmLikelihood(
//Init arrays:
logLikelihood_.resize(nbSites_ * nbStates_);
-
+
//Compute:
computeForward_();
}
+void LogsumHmmLikelihood::setNamespace(const std::string& nameSpace)
+{
+ AbstractParametrizable::setNamespace(nameSpace);
+
+ hiddenAlphabet_->setNamespace(nameSpace);
+ transitionMatrix_->setNamespace(nameSpace);
+ emissionProbabilities_->setNamespace(nameSpace);
+}
+
void LogsumHmmLikelihood::fireParameterChanged(const ParameterList& pl)
{
dVariable_="";
@@ -103,9 +115,14 @@ void LogsumHmmLikelihood::fireParameterChanged(const ParameterList& pl)
// (when both the alphabet and other parameter changed).
if (alphabetChanged && !transitionsChanged) transitionMatrix_->setParametersValues(transitionMatrix_->getParameters());
if (alphabetChanged && !emissionChanged) emissionProbabilities_->setParametersValues(emissionProbabilities_->getParameters());
-
- computeForward_();
+
backLogLikelihoodUpToDate_=false;
+ computeLikelihood();
+}
+
+void LogsumHmmLikelihood::computeLikelihood()
+{
+ computeForward_();
}
/***************************************************************************************************************************/
@@ -124,18 +141,19 @@ void LogsumHmmLikelihood::computeForward_()
}
//Initialisation:
- const vector<double>* emissions = &(*emissionProbabilities_)(0);
-
+ const vector<double>* emissions = &(* emissionProbabilities_)(0);
+
for (size_t j = 0; j < nbStates_; j++)
{
size_t jj = j * nbStates_;
x = logTrans[jj] + log(transitionMatrix_->getEquilibriumFrequencies()[0]);
-
+
for (size_t k = 1; k < nbStates_; k++)
{
a = logTrans[k + jj] + log(transitionMatrix_->getEquilibriumFrequencies()[k]);
x = NumTools::logsum(x, a);
}
+
logLikelihood_[j] = log((*emissions)[j]) + x;
}
@@ -374,9 +392,7 @@ void LogsumHmmLikelihood::computeDForward_() const
partialDLogLikelihoods_.clear();
- double x;
-
- vector<double> num(nbStates_);
+ vector<double> num(nbStates_), num2(nbStates_);
//Transition probabilities:
const ColMatrix<double> trans(transitionMatrix_->getPij());
@@ -384,7 +400,7 @@ void LogsumHmmLikelihood::computeDForward_() const
//Initialisation:
const vector<double>* emissions = &(*emissionProbabilities_)(0);
const vector<double>* dEmissions = &emissionProbabilities_->getDEmissionProbabilities(0);
-
+
for (size_t j = 0; j < nbStates_; j++)
dLogLikelihood_[0][j] = (*dEmissions)[j] / (*emissions)[j];
@@ -401,36 +417,25 @@ void LogsumHmmLikelihood::computeDForward_() const
emissions = &(*emissionProbabilities_)(i);
dEmissions = &emissionProbabilities_->getDEmissionProbabilities(i);
+ for (size_t kp = 0; kp < nbStates_; kp++)
+ num[kp]=logLikelihood_[iip+kp];
+
+ num-=num[VectorTools::whichMax(num)];
+
if (i < nextBrkPt)
{
for (size_t j = 0; j < nbStates_; j++)
{
- x=(*dEmissions)[j]/(*emissions)[j];
+ num2=dLogLikelihood_[i-1]*trans.getCol(j);
- for (size_t k = 0; k < nbStates_; k++)
- {
- for (size_t kp = 0; kp < nbStates_; kp++)
- num[kp]=logLikelihood_[iip+kp]-logLikelihood_[iip+k];
-
- x+=dLogLikelihood_[i-1][k]*trans(k,j)/VectorTools::sumExp(num,trans.getCol(j));
- }
-
- dLogLikelihood_[i][j] = x;
+ dLogLikelihood_[i][j] = (*dEmissions)[j]/(*emissions)[j] + VectorTools::sumExp(num,num2)/VectorTools::sumExp(num,trans.getCol(j));
}
}
else //Reset markov chain:
{
//Termination of previous segment
- x = 0;
- for (size_t k = 0; k < nbStates_; k++)
- {
- for (size_t kp = 0; kp < nbStates_; kp++)
- num[kp]=logLikelihood_[iip+kp]-logLikelihood_[iip+k];
-
- x += dLogLikelihood_[i-1][k] / VectorTools::sumExp(num);
- }
-
- partialDLogLikelihoods_.push_back(x);
+
+ partialDLogLikelihoods_.push_back(VectorTools::sumExp(num,dLogLikelihood_[i-1])/VectorTools::sumExp(num));
for (size_t j = 0; j < nbStates_; j++)
dLogLikelihood_[i][j] = (*dEmissions)[j] / (*emissions)[j];
@@ -444,17 +449,13 @@ void LogsumHmmLikelihood::computeDForward_() const
}
//Termination:
- x=0;
- for (size_t k = 0; k < nbStates_; k++)
- {
- for (size_t kp = 0; kp < nbStates_; kp++)
- num[kp]=logLikelihood_[nbStates_*(nbSites_-1)+kp]-logLikelihood_[nbStates_*(nbSites_-1)+k];
+ for (size_t kp = 0; kp < nbStates_; kp++)
+ num[kp]=logLikelihood_[nbStates_*(nbSites_-1)+kp];
+
+ num-=num[VectorTools::whichMax(num)];
- x += dLogLikelihood_[nbSites_-1][k] / VectorTools::sumExp(num);
- }
-
- partialDLogLikelihoods_.push_back(x);
-
+ partialDLogLikelihoods_.push_back(VectorTools::sumExp(num,dLogLikelihood_[nbSites_-1])/VectorTools::sumExp(num));
+
//Compute dLogLikelihood
dLogLik_ = 0;
@@ -464,6 +465,11 @@ void LogsumHmmLikelihood::computeDForward_() const
dLogLik_ += copy[i - 1];
}
+double LogsumHmmLikelihood::getDLogLikelihoodForASite(size_t site) const
+{
+ return partialDLogLikelihoods_[site];
+}
+
/***************************************************************************************************************************/
void LogsumHmmLikelihood::computeD2Forward_() const
@@ -480,9 +486,7 @@ void LogsumHmmLikelihood::computeD2Forward_() const
partialD2LogLikelihoods_.clear();
- double x, z, snum;
-
- vector<double> num(nbStates_);
+ vector<double> num(nbStates_),num2(nbStates_),num3(nbStates_);
//Transition probabilities:
const ColMatrix<double> trans(transitionMatrix_->getPij());
@@ -509,45 +513,33 @@ void LogsumHmmLikelihood::computeD2Forward_() const
dEmissions = &emissionProbabilities_->getDEmissionProbabilities(i);
d2Emissions = &emissionProbabilities_->getD2EmissionProbabilities(i);
+ for (size_t kp = 0; kp < nbStates_; kp++)
+ num[kp]=logLikelihood_[iip+kp];
+
+ num-=num[VectorTools::whichMax(num)];
+
if (i < nextBrkPt)
{
for (size_t j = 0; j < nbStates_; j++)
{
- x=(*d2Emissions)[j] / (*emissions)[j] - pow((*dEmissions)[j] / (*emissions)[j],2);
-
- for (size_t k = 0; k < nbStates_; k++)
- {
- for (size_t kp = 0; kp < nbStates_; kp++)
- num[kp]=logLikelihood_[iip+kp]-logLikelihood_[iip+k];
- snum=VectorTools::sumExp(num,trans.getCol(j));
+ double den=VectorTools::sumExp(num,trans.getCol(j));
-
- z=d2LogLikelihood_[i-1][k]+pow(dLogLikelihood_[i-1][k],2)
- - dLogLikelihood_[i-1][k] * VectorTools::sumExp(num, trans.getCol(j) * dLogLikelihood_[i-1])/snum;
+ num2=dLogLikelihood_[i-1]*trans.getCol(j);
- x += z * trans(k,j) / snum;
- }
+ num3=(dLogLikelihood_[i-1]*dLogLikelihood_[i-1]+d2LogLikelihood_[i-1])*trans.getCol(j);
- d2LogLikelihood_[i][j] = x;
+ d2LogLikelihood_[i][j] = VectorTools::sumExp(num,num3)/den - pow(VectorTools::sumExp(num,num2)/den,2);
}
}
else //Reset markov chain:
{
- x=0;
-
//Termination of previous segment:
- for (size_t k = 1; k < nbStates_; k++)
- {
- for (size_t kp = 0; kp < nbStates_; kp++)
- num[kp]=logLikelihood_[iip+kp]-logLikelihood_[iip+k];
-
- snum=VectorTools::sumExp(num);
-
- x += (d2LogLikelihood_[i-1][k]+pow(dLogLikelihood_[i-1][k],2)
- - dLogLikelihood_[i-1][k] * VectorTools::sumExp(num, dLogLikelihood_[i-1])/snum)/snum;
- }
-
- partialD2LogLikelihoods_.push_back(x);
+
+ double den=VectorTools::sumExp(num);
+
+ num2=dLogLikelihood_[i-1]*dLogLikelihood_[i-1]+d2LogLikelihood_[i-1];
+
+ partialD2LogLikelihoods_.push_back(VectorTools::sumExp(num,num2)/den-pow(VectorTools::sumExp(num,dLogLikelihood_[i-1])/den,2));
for (size_t j = 0; j < nbStates_; j++)
d2LogLikelihood_[i][j] = (*d2Emissions)[j] / (*emissions)[j] - pow((*dEmissions)[j] / (*emissions)[j],2);
@@ -560,21 +552,19 @@ void LogsumHmmLikelihood::computeD2Forward_() const
}
//Termination:
- x=0;
- for (size_t k = 0; k < nbStates_; k++)
- {
- for (size_t kp = 0; kp < nbStates_; kp++)
- num[kp]=logLikelihood_[nbStates_*(nbSites_-1)+kp]-logLikelihood_[nbStates_*(nbSites_-1)+k];
-
- snum=VectorTools::sumExp(num);
-
- x += (d2LogLikelihood_[nbSites_-1][k]+pow(dLogLikelihood_[nbSites_-1][k],2)
- - dLogLikelihood_[nbSites_-1][k] * VectorTools::sumExp(num, dLogLikelihood_[nbSites_-1])/snum)/snum;
- }
+ for (size_t kp = 0; kp < nbStates_; kp++)
+ num[kp]=logLikelihood_[nbStates_*(nbSites_-1)+kp];
+
+ num-=num[VectorTools::whichMax(num)];
+
+ double den=VectorTools::sumExp(num);
+
+ num2=dLogLikelihood_[nbSites_-1]*dLogLikelihood_[nbSites_-1]+d2LogLikelihood_[nbSites_-1];
+
+ partialD2LogLikelihoods_.push_back(VectorTools::sumExp(num,num2)/den-pow(VectorTools::sumExp(num,dLogLikelihood_[nbSites_-1])/den,2));
- partialD2LogLikelihoods_.push_back(x);
- //Compute dLogLikelihood
+ //Compute d2LogLikelihood
d2LogLik_ = 0;
vector<double> copy = partialD2LogLikelihoods_; //We need to keep the original order for posterior decoding.
@@ -582,3 +572,8 @@ void LogsumHmmLikelihood::computeD2Forward_() const
for (size_t i = copy.size(); i > 0; --i)
d2LogLik_ += copy[i - 1];
}
+
+double LogsumHmmLikelihood::getD2LogLikelihoodForASite(size_t site) const
+{
+ return partialD2LogLikelihoods_[site];
+}
diff --git a/src/Bpp/Numeric/Hmm/LogsumHmmLikelihood.h b/src/Bpp/Numeric/Hmm/LogsumHmmLikelihood.h
index b896044..67158e9 100644
--- a/src/Bpp/Numeric/Hmm/LogsumHmmLikelihood.h
+++ b/src/Bpp/Numeric/Hmm/LogsumHmmLikelihood.h
@@ -70,10 +70,18 @@ namespace bpp {
/**
* @brief The alphabet describing the hidden states.
*/
- std::auto_ptr<HmmStateAlphabet> hiddenAlphabet_;
- std::auto_ptr<HmmTransitionMatrix> transitionMatrix_;
- std::auto_ptr<HmmEmissionProbabilities> emissionProbabilities_;
+ HmmStateAlphabet* hiddenAlphabet_;
+ HmmTransitionMatrix* transitionMatrix_;
+ HmmEmissionProbabilities* emissionProbabilities_;
+
+ /**
+ * @brief Owns previous objects
+ *
+ */
+
+ bool ownsPointers_;
+
/**
* @brief The likelihood array.
*
@@ -119,48 +127,81 @@ namespace bpp {
/**
* @brief Build a new LogsumHmmLikelihood object.
*
- * @warning the HmmTransitionMatrix and HmmEmissionProbabilities object passed as argument must be non-null
- * and point toward the same HmmStateAlphabet instance. The three object will be copied if needed, and
- * deleted when the hmm likelihood objet is deleted. You should secure a copy before if you don't want them to
- * be destroyed with this object.
+ * @warning the HmmTransitionMatrix and HmmEmissionProbabilities
+ * object passed as argument must be non-null and point toward the
+ * same HmmStateAlphabet instance.
+ *
+ * @warning If ownsPointers_, The three object will be copied if
+ * needed, and deleted when the hmm likelihood objet is deleted.
+ * You should secure a copy before if you don't want them to be
+ * destroyed with this object.
*/
+
LogsumHmmLikelihood(
- HmmStateAlphabet* hiddenAlphabet,
- HmmTransitionMatrix* transitionMatrix,
- HmmEmissionProbabilities* emissionProbabilities,
- const std::string& prefix) throw (Exception);
+ HmmStateAlphabet* hiddenAlphabet,
+ HmmTransitionMatrix* transitionMatrix,
+ HmmEmissionProbabilities* emissionProbabilities,
+ bool ownsPointers_ = true,
+ const std::string& prefix = "") throw (Exception);
LogsumHmmLikelihood(const LogsumHmmLikelihood& lik):
- AbstractHmmLikelihood(lik),
- AbstractParametrizable(lik),
- hiddenAlphabet_(dynamic_cast<HmmStateAlphabet*>(lik.hiddenAlphabet_->clone())),
- transitionMatrix_(dynamic_cast<HmmTransitionMatrix*>(lik.transitionMatrix_->clone())),
- emissionProbabilities_(dynamic_cast<HmmEmissionProbabilities*>(lik.emissionProbabilities_->clone())),
- logLikelihood_(lik.logLikelihood_),
- partialLogLikelihoods_(lik.partialLogLikelihoods_),
- logLik_(lik.logLik_),
- dLogLikelihood_(lik.dLogLikelihood_),
- partialDLogLikelihoods_(lik.partialDLogLikelihoods_),
- d2LogLikelihood_(lik.d2LogLikelihood_),
- partialD2LogLikelihoods_(lik.partialD2LogLikelihoods_),
- backLogLikelihood_(lik.backLogLikelihood_),
- backLogLikelihoodUpToDate_(lik.backLogLikelihoodUpToDate_),
- breakPoints_(lik.breakPoints_),
- nbStates_(lik.nbStates_),
- nbSites_(lik.nbSites_)
+ AbstractHmmLikelihood(lik),
+ AbstractParametrizable(lik),
+ hiddenAlphabet_(),
+ transitionMatrix_(),
+ emissionProbabilities_(),
+ ownsPointers_(lik.ownsPointers_),
+ logLikelihood_(lik.logLikelihood_),
+ partialLogLikelihoods_(lik.partialLogLikelihoods_),
+ logLik_(lik.logLik_),
+ dLogLikelihood_(lik.dLogLikelihood_),
+ partialDLogLikelihoods_(lik.partialDLogLikelihoods_),
+ d2LogLikelihood_(lik.d2LogLikelihood_),
+ partialD2LogLikelihoods_(lik.partialD2LogLikelihoods_),
+ backLogLikelihood_(lik.backLogLikelihood_),
+ backLogLikelihoodUpToDate_(lik.backLogLikelihoodUpToDate_),
+ breakPoints_(lik.breakPoints_),
+ nbStates_(lik.nbStates_),
+ nbSites_(lik.nbSites_)
{
+ if (ownsPointers_)
+ {
+ hiddenAlphabet_=dynamic_cast<HmmStateAlphabet*>(lik.hiddenAlphabet_->clone());
+ transitionMatrix_=dynamic_cast<HmmTransitionMatrix*>(lik.transitionMatrix_->clone());
+ emissionProbabilities_=dynamic_cast<HmmEmissionProbabilities*>(lik.emissionProbabilities_->clone());
+ }
+ else
+ {
+ hiddenAlphabet_=lik.hiddenAlphabet_;
+ transitionMatrix_=lik.transitionMatrix_;
+ emissionProbabilities_=lik.emissionProbabilities_;
+ }
+
// Now adjust pointers:
- transitionMatrix_->setHmmStateAlphabet(hiddenAlphabet_.get());
- emissionProbabilities_->setHmmStateAlphabet(hiddenAlphabet_.get());
+ transitionMatrix_->setHmmStateAlphabet(hiddenAlphabet_);
+ emissionProbabilities_->setHmmStateAlphabet(hiddenAlphabet_);
}
LogsumHmmLikelihood& operator=(const LogsumHmmLikelihood& lik)
{
AbstractHmmLikelihood::operator=(lik);
AbstractParametrizable::operator =(lik);
- hiddenAlphabet_ = std::auto_ptr<HmmStateAlphabet>(dynamic_cast<HmmStateAlphabet*>(lik.hiddenAlphabet_->clone()));
- transitionMatrix_ = std::auto_ptr<HmmTransitionMatrix>(dynamic_cast<HmmTransitionMatrix*>(lik.transitionMatrix_->clone()));
- emissionProbabilities_ = std::auto_ptr<HmmEmissionProbabilities>(dynamic_cast<HmmEmissionProbabilities*>(lik.emissionProbabilities_->clone()));
+
+ ownsPointers_=lik.ownsPointers_;
+
+ if (ownsPointers_)
+ {
+ hiddenAlphabet_ = dynamic_cast<HmmStateAlphabet*>(lik.hiddenAlphabet_->clone());
+ transitionMatrix_ = dynamic_cast<HmmTransitionMatrix*>(lik.transitionMatrix_->clone());
+ emissionProbabilities_ = dynamic_cast<HmmEmissionProbabilities*>(lik.emissionProbabilities_->clone());
+ }
+ else
+ {
+ hiddenAlphabet_=lik.hiddenAlphabet_;
+ transitionMatrix_=lik.transitionMatrix_;
+ emissionProbabilities_=lik.emissionProbabilities_;
+ }
+
logLikelihood_ = lik.logLikelihood_;
partialLogLikelihoods_ = lik.partialLogLikelihoods_;
dLogLikelihood_ = lik.dLogLikelihood_;
@@ -175,19 +216,22 @@ namespace bpp {
nbSites_ = lik.nbSites_;
// Now adjust pointers:
- transitionMatrix_->setHmmStateAlphabet(hiddenAlphabet_.get());
- emissionProbabilities_->setHmmStateAlphabet(hiddenAlphabet_.get());
+ transitionMatrix_->setHmmStateAlphabet(hiddenAlphabet_);
+ emissionProbabilities_->setHmmStateAlphabet(hiddenAlphabet_);
return *this;
}
- virtual ~LogsumHmmLikelihood() {}
+ virtual ~LogsumHmmLikelihood() {
+ if (ownsPointers_)
+ {
+ delete hiddenAlphabet_;
+ delete transitionMatrix_;
+ delete emissionProbabilities_;
+ }
+ }
+
-#ifndef NO_VIRTUAL_COV
- LogsumHmmLikelihood*
-#else
- Clonable*
-#endif
- clone() const { return new LogsumHmmLikelihood(*this); }
+ LogsumHmmLikelihood* clone() const { return new LogsumHmmLikelihood(*this); }
public:
const HmmStateAlphabet& getHmmStateAlphabet() const { return *hiddenAlphabet_; }
@@ -218,16 +262,25 @@ namespace bpp {
double getLikelihoodForASite(size_t site) const;
+ double getDLogLikelihoodForASite(size_t site) const;
+
+ double getD2LogLikelihoodForASite(size_t site) const;
+
Vdouble getLikelihoodForEachSite() const;
- virtual void fireParameterChanged(const ParameterList& pl);
+ void setNamespace(const std::string& nameSpace);
+
+ void fireParameterChanged(const ParameterList& pl);
Vdouble getHiddenStatesPosteriorProbabilitiesForASite(size_t site) const;
void getHiddenStatesPosteriorProbabilities(std::vector< std::vector<double> >& probs, bool append = false) const throw (Exception);
+ void computeLikelihood();
protected:
+
void computeForward_();
+
void computeBackward_() const;
void computeDLikelihood_() const
diff --git a/src/Bpp/Numeric/Hmm/LowMemoryRescaledHmmLikelihood.cpp b/src/Bpp/Numeric/Hmm/LowMemoryRescaledHmmLikelihood.cpp
index 21639b8..1a21fd3 100644
--- a/src/Bpp/Numeric/Hmm/LowMemoryRescaledHmmLikelihood.cpp
+++ b/src/Bpp/Numeric/Hmm/LowMemoryRescaledHmmLikelihood.cpp
@@ -87,6 +87,15 @@ LowMemoryRescaledHmmLikelihood::LowMemoryRescaledHmmLikelihood(
computeForward_();
}
+void LowMemoryRescaledHmmLikelihood::setNamespace(const std::string& nameSpace)
+{
+ AbstractParametrizable::setNamespace(nameSpace);
+
+ hiddenAlphabet_->setNamespace(nameSpace);
+ transitionMatrix_->setNamespace(nameSpace);
+ emissionProbabilities_->setNamespace(nameSpace);
+}
+
void LowMemoryRescaledHmmLikelihood::fireParameterChanged(const ParameterList& pl)
{
bool alphabetChanged = hiddenAlphabet_->matchParametersValues(pl);
diff --git a/src/Bpp/Numeric/Hmm/LowMemoryRescaledHmmLikelihood.h b/src/Bpp/Numeric/Hmm/LowMemoryRescaledHmmLikelihood.h
index a9e797a..4ab7162 100644
--- a/src/Bpp/Numeric/Hmm/LowMemoryRescaledHmmLikelihood.h
+++ b/src/Bpp/Numeric/Hmm/LowMemoryRescaledHmmLikelihood.h
@@ -71,9 +71,9 @@ private:
/**
* @brief The alphabet describing the hidden states.
*/
- std::auto_ptr<HmmStateAlphabet> hiddenAlphabet_;
- std::auto_ptr<HmmTransitionMatrix> transitionMatrix_;
- std::auto_ptr<HmmEmissionProbabilities> emissionProbabilities_;
+ std::unique_ptr<HmmStateAlphabet> hiddenAlphabet_;
+ std::unique_ptr<HmmTransitionMatrix> transitionMatrix_;
+ std::unique_ptr<HmmEmissionProbabilities> emissionProbabilities_;
/**
* @brief The likelihood array.
@@ -135,9 +135,9 @@ public:
{
AbstractHmmLikelihood::operator=(lik);
AbstractParametrizable::operator=(lik);
- hiddenAlphabet_ = std::auto_ptr<HmmStateAlphabet>(dynamic_cast<HmmStateAlphabet*>(lik.hiddenAlphabet_->clone()));
- transitionMatrix_ = std::auto_ptr<HmmTransitionMatrix>(dynamic_cast<HmmTransitionMatrix*>(lik.transitionMatrix_->clone()));
- emissionProbabilities_ = std::auto_ptr<HmmEmissionProbabilities>(dynamic_cast<HmmEmissionProbabilities*>(lik.emissionProbabilities_->clone()));
+ hiddenAlphabet_ = std::unique_ptr<HmmStateAlphabet>(dynamic_cast<HmmStateAlphabet*>(lik.hiddenAlphabet_->clone()));
+ transitionMatrix_ = std::unique_ptr<HmmTransitionMatrix>(dynamic_cast<HmmTransitionMatrix*>(lik.transitionMatrix_->clone()));
+ emissionProbabilities_ = std::unique_ptr<HmmEmissionProbabilities>(dynamic_cast<HmmEmissionProbabilities*>(lik.emissionProbabilities_->clone()));
likelihood1_ = lik.likelihood1_;
likelihood2_ = lik.likelihood2_;
logLik_ = lik.logLik_;
@@ -154,12 +154,7 @@ public:
virtual ~LowMemoryRescaledHmmLikelihood() {}
-#ifndef NO_VIRTUAL_COV
- LowMemoryRescaledHmmLikelihood*
-#else
- Clonable*
-#endif
- clone() const { return new LowMemoryRescaledHmmLikelihood(*this); }
+ LowMemoryRescaledHmmLikelihood* clone() const { return new LowMemoryRescaledHmmLikelihood(*this); }
public:
const HmmStateAlphabet& getHmmStateAlphabet() const { return *hiddenAlphabet_; }
@@ -187,8 +182,9 @@ public:
double getLogLikelihood() const { return logLik_; }
- void fireParameterChanged(const ParameterList& pl);
+ void setNamespace(const std::string& nameSpace);
+ void fireParameterChanged(const ParameterList& pl);
double getLikelihoodForASite(size_t site) const
{
@@ -216,13 +212,26 @@ protected:
void computeDLikelihood_() const
{
- // computeDForward_();
+ throw (NotImplementedException("LowMemoryRescaledHmmLikelihood::computeDLikelihood_. Use RescaledHmmLikelihood instead."));
}
void computeD2Likelihood_() const
{
- // computeD2Forward_();
+ throw (NotImplementedException("LowMemoryRescaledHmmLikelihood::computeD2Likelihood_. Use RescaledHmmLikelihood instead."));
+ }
+
+ double getDLogLikelihoodForASite(size_t site) const
+ {
+ throw (NotImplementedException("LowMemoryRescaledHmmLikelihood::getDLogLikelihoodForASite. Use RescaledHmmLikelihood instead."));
+ return 0;
}
+
+ double getD2LogLikelihoodForASite(size_t site) const
+ {
+ throw (NotImplementedException("LowMemoryRescaledHmmLikelihood::getD2LogLikelihoodForASite. Use RescaledHmmLikelihood instead."));
+ return 0;
+ }
+
};
}
diff --git a/src/Bpp/Numeric/Hmm/RescaledHmmLikelihood.cpp b/src/Bpp/Numeric/Hmm/RescaledHmmLikelihood.cpp
index 5cb884d..d2a93d1 100644
--- a/src/Bpp/Numeric/Hmm/RescaledHmmLikelihood.cpp
+++ b/src/Bpp/Numeric/Hmm/RescaledHmmLikelihood.cpp
@@ -94,6 +94,15 @@ RescaledHmmLikelihood::RescaledHmmLikelihood(
computeForward_();
}
+void RescaledHmmLikelihood::setNamespace(const std::string& nameSpace)
+{
+ AbstractParametrizable::setNamespace(nameSpace);
+
+ hiddenAlphabet_->setNamespace(nameSpace);
+ transitionMatrix_->setNamespace(nameSpace);
+ emissionProbabilities_->setNamespace(nameSpace);
+}
+
void RescaledHmmLikelihood::fireParameterChanged(const ParameterList& pl)
{
bool alphabetChanged = hiddenAlphabet_->matchParametersValues(pl);
@@ -124,7 +133,7 @@ void RescaledHmmLikelihood::computeForward_()
size_t ii = i * nbStates_;
for (size_t j = 0; j < nbStates_; j++) {
trans[ii + j] = transitionMatrix_->Pij(j, i);
- if (isnan(trans[ii + j]))
+ if (std::isnan(trans[ii + j]))
throw Exception("RescaledHmmLikelihood::computeForward_. NaN transition probability");
if (trans[ii + j] < 0)
throw Exception("RescaledHmmLikelihood::computeForward_. Negative transition probability: " + TextTools::toString(trans[ii + j]));
@@ -239,12 +248,12 @@ void RescaledHmmLikelihood::computeForward_()
void RescaledHmmLikelihood::computeBackward_() const
{
- if (backLikelihood_.size()==0)
- {
- backLikelihood_.resize(nbSites_);
- for (size_t i=0;i<nbSites_;i++)
- backLikelihood_[i].resize(nbStates_);
- }
+ if (backLikelihood_.size() == 0)
+ {
+ backLikelihood_.resize(nbSites_);
+ for (size_t i = 0; i < nbSites_; i++)
+ backLikelihood_[i].resize(nbStates_);
+ }
double x;
@@ -299,17 +308,17 @@ void RescaledHmmLikelihood::computeBackward_() const
}
}
- backLikelihoodUpToDate_=true;
+ backLikelihoodUpToDate_ = true;
}
/***************************************************************************************************************************/
double RescaledHmmLikelihood::getLikelihoodForASite(size_t site) const
{
- Vdouble probs=getHiddenStatesPosteriorProbabilitiesForASite(site);
- double x=0;
- for (size_t i=0;i<nbStates_;i++)
- x+=probs[i]*(*emissionProbabilities_)(site,i);
+ Vdouble probs = getHiddenStatesPosteriorProbabilitiesForASite(site);
+ double x = 0;
+ for (size_t i = 0; i < nbStates_; i++)
+ x += probs[i] * (*emissionProbabilities_)(site,i);
return x;
}
@@ -320,11 +329,11 @@ Vdouble RescaledHmmLikelihood::getLikelihoodForEachSite() const
getHiddenStatesPosteriorProbabilities(vv);
Vdouble ret(nbSites_);
- for (size_t i=0;i<nbSites_;i++)
+ for (size_t i = 0; i < nbSites_; i++)
{
- ret[i]=0;
- for (size_t j=0;j<nbStates_;j++)
- ret[i]+=vv[i][j]*(*emissionProbabilities_)(i,j);
+ ret[i] = 0;
+ for (size_t j = 0; j < nbStates_; j++)
+ ret[i] += vv[i][j] * (*emissionProbabilities_)(i,j);
}
return ret;
@@ -353,21 +362,21 @@ void RescaledHmmLikelihood::getHiddenStatesPosteriorProbabilities(std::vector< s
size_t offset = append ? probs.size() : 0;
probs.resize(offset + nbSites_);
for (size_t i = 0; i < nbSites_; i++)
- {
- probs[offset + i].resize(nbStates_);
- }
+ {
+ probs[offset + i].resize(nbStates_);
+ }
if (!backLikelihoodUpToDate_)
computeBackward_();
for (size_t i = 0; i < nbSites_; i++)
+ {
+ size_t ii = i * nbStates_;
+ for (size_t j = 0; j < nbStates_; j++)
{
- size_t ii = i * nbStates_;
- for (size_t j = 0; j < nbStates_; j++)
- {
- probs[offset + i][j] = likelihood_[ii + j] * backLikelihood_[i][j];
- }
+ probs[offset + i][j] = likelihood_[ii + j] * backLikelihood_[i][j];
}
+ }
}
/***************************************************************************************************************************/
@@ -468,6 +477,11 @@ void RescaledHmmLikelihood::computeDForward_() const
}
}
+double RescaledHmmLikelihood::getDLogLikelihoodForASite(size_t site) const
+{
+ return dScales_[site]/scales_[site];
+}
+
/***************************************************************************************************************************/
@@ -575,3 +589,9 @@ void RescaledHmmLikelihood::computeD2Forward_() const
}
/***************************************************************************************************************************/
+
+double RescaledHmmLikelihood::getD2LogLikelihoodForASite(size_t site) const
+{
+ return d2Scales_[site]/scales_[site]-pow(dScales_[site]/scales_[site],2);
+}
+
diff --git a/src/Bpp/Numeric/Hmm/RescaledHmmLikelihood.h b/src/Bpp/Numeric/Hmm/RescaledHmmLikelihood.h
index 93f6ea9..0cb76cb 100644
--- a/src/Bpp/Numeric/Hmm/RescaledHmmLikelihood.h
+++ b/src/Bpp/Numeric/Hmm/RescaledHmmLikelihood.h
@@ -64,9 +64,9 @@ namespace bpp {
/**
* @brief The alphabet describing the hidden states.
*/
- std::auto_ptr<HmmStateAlphabet> hiddenAlphabet_;
- std::auto_ptr<HmmTransitionMatrix> transitionMatrix_;
- std::auto_ptr<HmmEmissionProbabilities> emissionProbabilities_;
+ std::unique_ptr<HmmStateAlphabet> hiddenAlphabet_;
+ std::unique_ptr<HmmTransitionMatrix> transitionMatrix_;
+ std::unique_ptr<HmmEmissionProbabilities> emissionProbabilities_;
/**
* @brief The likelihood arrays.
@@ -162,9 +162,9 @@ namespace bpp {
{
AbstractHmmLikelihood::operator=(lik);
AbstractParametrizable::operator=(lik);
- hiddenAlphabet_ = std::auto_ptr<HmmStateAlphabet>(dynamic_cast<HmmStateAlphabet*>(lik.hiddenAlphabet_->clone()));
- transitionMatrix_ = std::auto_ptr<HmmTransitionMatrix>(dynamic_cast<HmmTransitionMatrix*>(lik.transitionMatrix_->clone()));
- emissionProbabilities_ = std::auto_ptr<HmmEmissionProbabilities>(dynamic_cast<HmmEmissionProbabilities*>(lik.emissionProbabilities_->clone()));
+ hiddenAlphabet_ = std::unique_ptr<HmmStateAlphabet>(dynamic_cast<HmmStateAlphabet*>(lik.hiddenAlphabet_->clone()));
+ transitionMatrix_ = std::unique_ptr<HmmTransitionMatrix>(dynamic_cast<HmmTransitionMatrix*>(lik.transitionMatrix_->clone()));
+ emissionProbabilities_ = std::unique_ptr<HmmEmissionProbabilities>(dynamic_cast<HmmEmissionProbabilities*>(lik.emissionProbabilities_->clone()));
likelihood_ = lik.likelihood_;
dLikelihood_ = lik.dLikelihood_;
d2Likelihood_ = lik.d2Likelihood_;
@@ -186,12 +186,7 @@ namespace bpp {
virtual ~RescaledHmmLikelihood() {}
-#ifndef NO_VIRTUAL_COV
- RescaledHmmLikelihood*
-#else
- Clonable*
-#endif
- clone() const { return new RescaledHmmLikelihood(*this); }
+ RescaledHmmLikelihood* clone() const { return new RescaledHmmLikelihood(*this); }
public:
const HmmStateAlphabet& getHmmStateAlphabet() const { return *hiddenAlphabet_; }
@@ -222,8 +217,14 @@ namespace bpp {
double getLikelihoodForASite(size_t site) const;
+ double getDLogLikelihoodForASite(size_t site) const;
+
+ double getD2LogLikelihoodForASite(size_t site) const;
+
Vdouble getLikelihoodForEachSite() const;
+ void setNamespace(const std::string& nameSpace);
+
void fireParameterChanged(const ParameterList& pl);
Vdouble getHiddenStatesPosteriorProbabilitiesForASite(size_t site) const;
diff --git a/src/Bpp/Numeric/Matrix/Matrix.h b/src/Bpp/Numeric/Matrix/Matrix.h
index dac0a53..72393c6 100644
--- a/src/Bpp/Numeric/Matrix/Matrix.h
+++ b/src/Bpp/Numeric/Matrix/Matrix.h
@@ -129,7 +129,7 @@ template<class Scalar>
class RowMatrix :
public Matrix<Scalar>
{
-private:
+protected:
std::vector< std::vector<Scalar> > m_;
public:
@@ -173,7 +173,7 @@ public:
return *this;
}
- virtual ~RowMatrix() {}
+// virtual ~RowMatrix() {}
public:
RowMatrix* clone() const { return new RowMatrix(*this); }
@@ -198,6 +198,11 @@ public:
return m_[i];
}
+ std::vector<Scalar>& getRow(size_t i)
+ {
+ return m_[i];
+ }
+
std::vector<Scalar> col(size_t j) const
{
std::vector<Scalar> c(getNumberOfRows());
diff --git a/src/Bpp/Numeric/Matrix/MatrixTools.h b/src/Bpp/Numeric/Matrix/MatrixTools.h
index c988f29..3b3719b 100644
--- a/src/Bpp/Numeric/Matrix/MatrixTools.h
+++ b/src/Bpp/Numeric/Matrix/MatrixTools.h
@@ -161,6 +161,18 @@ namespace bpp
}
/**
+ * @brief Set all diagonal elements in M to value x.
+ * @param M A matrix.
+ * @param x The value to use.
+ */
+ template<class Matrix, class Scalar>
+ static void fillDiag(Matrix& M, Scalar x)
+ {
+ for (size_t i = 0; i < M.getNumberOfRows(); i++)
+ M(i, i) = x;
+ }
+
+ /**
* @brief Multiply all elements of a matrix by a given value, and add a constant.
*
* Performs \f$\forall i \forall j m_{i,j} = a.m_{i,j}+b\f$.
@@ -292,10 +304,11 @@ namespace bpp
/**
* @brief Add matrix B to matrix A.
*
- * @param A [in] Matrix A
+ * @param A [in, out] Matrix A
* @param B [in] Matrix B
* @throw DimensionException If A and B have note the same size.
*/
+
template<class MatrixA, class MatrixB>
static void add(MatrixA& A, const MatrixB& B) throw (DimensionException)
{
@@ -303,11 +316,13 @@ namespace bpp
size_t nrA = A.getNumberOfRows();
size_t nrB = B.getNumberOfRows();
size_t ncB = B.getNumberOfColumns();
- if (ncA != ncB) throw DimensionException("MatrixTools::operator+(). A and B must have the same number of colums.", ncB, ncA);
- if (nrA != nrB) throw DimensionException("MatrixTools::operator+(). A and B must have the same number of rows.", nrB, nrA);
- for (size_t i = 0; i < A.getNumberOfRows(); i++)
+ if (ncA > ncB) throw DimensionException("MatrixTools::operator+=(). A and B must have the same number of colums.", ncB, ncA);
+ if (nrA > nrB) throw DimensionException("MatrixTools::operator+=(). A and B must have the same number of rows.", nrB, nrA);
+
+
+ for (size_t i = 0; i < nrA; i++)
{
- for (size_t j = 0; j < A.getNumberOfColumns(); j++)
+ for (size_t j = 0; j < ncA; j++)
{
A(i, j) += B(i, j);
}
@@ -331,9 +346,10 @@ namespace bpp
size_t ncB = B.getNumberOfColumns();
if (ncA != ncB) throw DimensionException("MatrixTools::operator+(). A and B must have the same number of colums.", ncB, ncA);
if (nrA != nrB) throw DimensionException("MatrixTools::operator+(). A and B must have the same number of rows.", nrB, nrA);
- for (size_t i = 0; i < A.getNumberOfRows(); i++)
+
+ for (size_t i = 0; i < nrA; i++)
{
- for (size_t j = 0; j < A.getNumberOfColumns(); j++)
+ for (size_t j = 0; j < ncA; j++)
{
A(i, j) += x*B(i, j);
}
@@ -760,15 +776,19 @@ namespace bpp
* @param A [in] The first row matrix.
* @param B [in] The second row matrix.
* @param O [out] The product \f$A \otimes B\f$.
+ * @param check [optional] if resize of 0 (default: true)
*/
template<class Scalar>
- static void kroneckerMult(const Matrix<Scalar>& A, const Matrix<Scalar>& B, Matrix<Scalar>& O)
+ static void kroneckerMult(const Matrix<Scalar>& A, const Matrix<Scalar>& B, Matrix<Scalar>& O, bool check = true)
{
size_t ncA = A.getNumberOfColumns();
size_t nrA = A.getNumberOfRows();
size_t nrB = B.getNumberOfRows();
size_t ncB = B.getNumberOfColumns();
- O.resize(nrA * nrB, ncA * ncB);
+
+ if (check)
+ O.resize(nrA * nrB, ncA * ncB);
+
for (size_t ia = 0; ia < nrA; ia++)
{
for (size_t ja = 0; ja < ncA; ja++)
@@ -786,6 +806,80 @@ namespace bpp
}
/**
+ * @brief Compute the Kronecker product of one Matrice with a
+ * diagonal matrix, which main term and dimension are given
+ *
+ * @param A [in] The first row matrix.
+ * @param dim [in] The dimension of the diagonal matrix.
+ * @param v [in] The diagonal value of the diagonal matrix.
+ * @param O [out] The product \f$A \otimes B\f$.
+ * @param check [optional] if resize of 0 (default: true)
+ */
+ template<class Scalar>
+ static void kroneckerMult(const Matrix<Scalar>& A, size_t dim, const Scalar& v, Matrix<Scalar>& O, bool check = true)
+ {
+ size_t ncA = A.getNumberOfColumns();
+ size_t nrA = A.getNumberOfRows();
+
+ if (check)
+ O.resize(nrA * dim, ncA * dim);
+
+ for (size_t ia = 0; ia < nrA; ia++)
+ {
+ for (size_t ja = 0; ja < ncA; ja++)
+ {
+ Scalar aij = A(ia, ja);
+ for (size_t ib = 0; ib < dim; ib++)
+ {
+ for (size_t jb = 0; jb < dim; jb++)
+ {
+ O(ia * dim + ib, ja * dim + jb) = aij * ((ib==jb)?v:0);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @brief Compute the Kronecker product of two row matrices in
+ * which the diagonal element is changed
+ *
+ * @param A [in] The first row matrix.
+ * @param B [in] The second row matrix.
+ * @param dA [in] The replaced diagonal element of A
+ * @param dB [in] The replaced diagonal element of B
+ * @param O [out] The product \f$A \otimes B\f$.
+ * @param check [optional] if resize of 0 (default: true)
+ */
+ template<class Scalar>
+ static void kroneckerMult(const Matrix<Scalar>& A, const Matrix<Scalar>& B, const Scalar& dA, const Scalar& dB, Matrix<Scalar>& O, bool check= true)
+ {
+ size_t ncA = A.getNumberOfColumns();
+ size_t nrA = A.getNumberOfRows();
+ size_t nrB = B.getNumberOfRows();
+ size_t ncB = B.getNumberOfColumns();
+
+ if (check)
+ O.resize(nrA * nrB, ncA * ncB);
+
+ for (size_t ia = 0; ia < nrA; ia++)
+ {
+ for (size_t ja = 0; ja < ncA; ja++)
+ {
+ const Scalar& aij = (ia==ja)?dA:A(ia, ja);
+
+ for (size_t ib = 0; ib < nrB; ib++)
+ {
+ for (size_t jb = 0; jb < ncB; jb++)
+ {
+ O(ia * nrB + ib, ja * ncB + jb) = aij * ((ib==jb)?dB:B(ib, jb));
+ }
+ }
+ }
+ }
+ }
+
+ /**
* @brief Compute the Hadamard product of two row matrices with same dimensions.
*
* @param A [in] The first row matrix.
@@ -851,20 +945,21 @@ namespace bpp
}
/**
- * @brief Compute the Kronecker sum of two row matrices.
+ * @brief Compute the direct sum of two row matrices.
*
* @param A [in] The first row matrix.
* @param B [in] The second row matrix.
- * @param O [out] The product \f$A \oplus B\f$.
+ * @param O [out] The sum \f$A \oplus B\f$.
*/
template<class Scalar>
- static void kroneckerSum(const Matrix<Scalar>& A, const Matrix<Scalar>& B, Matrix<Scalar>& O)
+ static void directSum(const Matrix<Scalar>& A, const Matrix<Scalar>& B, Matrix<Scalar>& O)
{
size_t ncA = A.getNumberOfColumns();
size_t nrA = A.getNumberOfRows();
size_t nrB = B.getNumberOfRows();
size_t ncB = B.getNumberOfColumns();
O.resize(nrA + nrB, ncA + ncB);
+
for (size_t ia = 0; ia < nrA; ia++)
{
for (size_t ja = 0; ja < ncA; ja++)
@@ -872,6 +967,23 @@ namespace bpp
O(ia, ja) = A(ia, ja);
}
}
+
+ for (size_t ia = 0; ia < nrA; ia++)
+ {
+ for (size_t jb = 0; jb < ncB; jb++)
+ {
+ O(ia, ncA + jb) = 0;
+ }
+ }
+
+ for (size_t ib = 0; ib < nrB; ib++)
+ {
+ for (size_t ja = 0; ja < ncA; ja++)
+ {
+ O(nrA + ib, ja) = 0;
+ }
+ }
+
for (size_t ib = 0; ib < nrB; ib++)
{
for (size_t jb = 0; jb < nrB; jb++)
@@ -882,13 +994,13 @@ namespace bpp
}
/**
- * @brief Compute the Kronecker sum of n row matrices.
+ * @brief Compute the direct sum of n row matrices.
*
* @param vA [in] A vector of row matrices of any size.
- * @param O [out] The product \f$\bigoplus_i A_i\f$.
+ * @param O [out] The sum \f$\bigoplus_i A_i\f$.
*/
template<class Scalar>
- static void kroneckerSum(const std::vector< Matrix<Scalar>*>& vA, Matrix<Scalar>& O)
+ static void directSum(const std::vector< Matrix<Scalar>*>& vA, Matrix<Scalar>& O)
{
size_t nr = 0;
size_t nc = 0;
@@ -898,6 +1010,10 @@ namespace bpp
nc += vA[k]->getNumberOfColumns();
}
O.resize(nr, nc);
+ for (size_t k=0; k<nr; k++)
+ for (size_t k2=0; k2<nc; k2++)
+ O(k,k2)=0;
+
size_t rk = 0; // Row counter
size_t ck = 0; // Col counter
for (size_t k = 0; k < vA.size(); k++)
@@ -1240,71 +1356,6 @@ namespace bpp
};
-/* DEPRECATED
- namespace MatrixOperators {
-
- MatrixB operator*(const MatrixA & A, const MatrixB & B) throw (DimensionException)
- {
- return MatrixTools::mult<MatrixA, MatrixB>(A, B);
- }
-
- template<class MatrixA, class MatrixB>
- MatrixA operator+(const MatrixA & A, const MatrixB & B) throw (DimensionException)
- {
- MatrixA C = A;
- MatrixTools::add<MatrixA, MatrixB>(C, B);
- return C;
- }
-
- template<class MatrixA, class MatrixB>
- MatrixA operator+=(MatrixA & A, const MatrixB & B) throw (DimensionException)
- {
- MatrixTools::add<MatrixA, MatrixB>(A, B);
- return A;
- }
-
- template<class Matrix>
- Matrix operator-(const Matrix A)
- {
- Matrix B(A.getNumberOfRows(), A.getNumberOfColumns());
- for(size_t i = 0; i < B.getNumberOfRows(); i++) {
- for(size_t j = 0; j < B.getNumberOfColumns(); j++) {
- B(i, j) = -A(i, j);
- }
- }
- return B;
- }
-
- template<class MatrixA, class MatrixB>
- MatrixA operator-(const MatrixA & A, const MatrixB & B) throw (DimensionException)
- {
- // size_t ncA = A.getNumberOfColumns();
- // size_t nrA = A.getNumberOfRows();
- // size_t nrB = B.getNumberOfRows();
- // size_t ncB = B.getNumberOfColumns();
- // if(ncA != ncB) throw DimensionException("MatrixTools::operator-(). A and B must have the same number of colums.", ncB, ncA);
- // if(nrA != nrB) throw DimensionException("MatrixTools::operator-(). A and B must have the same number of rows.", nrB, nrA);
- // MatrixB C(A.getNumberOfRows(), A.getNumberOfColumns());
- // for(size_t i = 0; i < A.getNumberOfRows(); i++) {
- // for(size_t j = 0; j < A.getNumberOfColumns(); j++) {
- // C(i, j) = A(i, j) - B(i, j);
- // }
- // }
- // return C;
- MatrixA C = A;
- MatrixTools::add<MatrixA, MatrixB>(C, -B);
- return C;
- }
-
- template<class MatrixA, class MatrixB>
- MatrixA operator-=(MatrixA & A, const MatrixB & B) throw (DimensionException)
- {
- MatrixTools::add<MatrixA, MatrixB>(A, -B);
- return A;
- }
-
- };
-*/
} // end of namespace bpp.
#endif // _MATRIXTOOLS_H_
diff --git a/src/Bpp/Numeric/Number.h b/src/Bpp/Numeric/Number.h
index 7078d11..8b918aa 100644
--- a/src/Bpp/Numeric/Number.h
+++ b/src/Bpp/Numeric/Number.h
@@ -42,6 +42,7 @@ knowledge of the CeCILL license and that you accept its terms.
#define _NUMBER_H_
#include "../Clonable.h"
+#include "../Text/TextTools.h"
#include <string>
diff --git a/src/Bpp/Numeric/Parameter.h b/src/Bpp/Numeric/Parameter.h
index 1ed95d2..9f3a99c 100644
--- a/src/Bpp/Numeric/Parameter.h
+++ b/src/Bpp/Numeric/Parameter.h
@@ -70,12 +70,7 @@ namespace bpp
return *this;
}
-#ifndef NO_VIRTUAL_COV
- ParameterEvent*
-#else
- Clonable*
-#endif
- clone() const { return new ParameterEvent(*this); }
+ ParameterEvent* clone() const { return new ParameterEvent(*this); }
public:
const Parameter* getParameter() const { return parameter_; }
@@ -93,12 +88,7 @@ namespace bpp
public virtual Clonable
{
public:
-#ifndef NO_VIRTUAL_COV
- ParameterListener*
-#else
- Clonable*
-#endif
- clone() const = 0;
+ ParameterListener* clone() const = 0;
public:
@@ -191,12 +181,7 @@ namespace bpp
virtual ~Parameter();
-#ifndef NO_VIRTUAL_COV
- Parameter*
-#else
- Clonable*
-#endif
- clone() const { return new Parameter(*this); }
+ Parameter* clone() const { return new Parameter(*this); }
public:
diff --git a/src/Bpp/Numeric/ParameterAliasable.h b/src/Bpp/Numeric/ParameterAliasable.h
index c634f96..b9c6f68 100644
--- a/src/Bpp/Numeric/ParameterAliasable.h
+++ b/src/Bpp/Numeric/ParameterAliasable.h
@@ -119,7 +119,6 @@ namespace bpp
**/
virtual void aliasParameters(std::map<std::string, std::string>& unparsedParams, bool verbose) = 0;
-
/**
* @brief Detach two parameters previously set as 'aliased'.
@@ -147,6 +146,14 @@ namespace bpp
* @param name The name of the parameter to look for.
*/
virtual std::vector<std::string> getAlias(const std::string& name) const = 0;
+
+ /**
+ * @return the map of the aliases.
+ *
+ **/
+
+ virtual std::map<std::string, std::string> getAliases() const = 0;
+
};
@@ -176,6 +183,7 @@ namespace bpp
void unaliasParameters(const std::string & p1, const std::string & p2) throw (ParameterNotFoundException, Exception) {}
unsigned int getNumberOfIndependentParameters() const{ return 0; }
std::vector<std::string> getAlias(const std::string& name) const { return std::vector<std::string>(); }
+ std::map<std::string, std::string> getAliases() const { return std::map<std::string, std::string>(); }
/** @} */
};
diff --git a/src/Bpp/Numeric/ParameterList.cpp b/src/Bpp/Numeric/ParameterList.cpp
index 0143376..35f8c34 100644
--- a/src/Bpp/Numeric/ParameterList.cpp
+++ b/src/Bpp/Numeric/ParameterList.cpp
@@ -52,9 +52,9 @@ ParameterList::ParameterList(const ParameterList& pl) :
parameters_(pl.size())
{
// Now copy all parameters:
- for (unsigned int i = 0; i < size(); i++)
+ for (size_t i = 0; i < size(); i++)
{
- parameters_[i] = dynamic_cast<Parameter*>(pl.parameters_[i]->clone());
+ parameters_[i] = shared_ptr<Parameter>(pl.parameters_[i]->clone());
}
}
@@ -62,16 +62,13 @@ ParameterList::ParameterList(const ParameterList& pl) :
ParameterList& ParameterList::operator=(const ParameterList& pl)
{
- // First delete all parameters:
- reset();
-
// Then resize the vector:
parameters_.resize(pl.size());
// Now copy all parameters:
- for (unsigned int i = 0; i < pl.size(); i++)
+ for (size_t i = 0; i < pl.size(); i++)
{
- parameters_[i] = dynamic_cast<Parameter*>(pl.parameters_[i]->clone());
+ parameters_[i] = shared_ptr<Parameter>(pl.parameters_[i]->clone());
}
return *this;
@@ -86,43 +83,75 @@ ParameterList::~ParameterList()
}
/******************************************************************************/
+
const Parameter& ParameterList::getParameter(const std::string& name) const throw (ParameterNotFoundException)
{
- for (unsigned int i = 0; i < size(); i++)
+ for (size_t i = 0; i < size(); i++)
{
- const Parameter* p = parameters_[i];
+ const Parameter* p = parameters_[i].get();
if (p->getName() == name) return *p;
}
throw ParameterNotFoundException("ParameterList::getParameter('name').", name);
}
/******************************************************************************/
+
+const shared_ptr<Parameter>& ParameterList::getSharedParameter(const std::string& name) const throw (ParameterNotFoundException)
+{
+ for (size_t i = 0; i < size(); i++)
+ {
+ const shared_ptr<Parameter>& p = parameters_[i];
+ if (p->getName() == name)
+ return p;
+ }
+ throw ParameterNotFoundException("ParameterList::getSharedParameter('name').", name);
+}
+
+
+/******************************************************************************/
+
double ParameterList::getParameterValue(const std::string& name) const throw (ParameterNotFoundException)
{
- for (unsigned int i = 0; i < size(); i++)
+ for (size_t i = 0; i < size(); i++)
{
- const Parameter* p = parameters_[i];
+ const Parameter* p = parameters_[i].get();
if (p->getName() == name) return p->getValue();
}
throw ParameterNotFoundException("ParameterList::getParameterValue('name').", name);
}
/******************************************************************************/
+
Parameter& ParameterList::getParameter(const std::string& name) throw (ParameterNotFoundException)
{
- for (unsigned int i = 0; i < size(); i++)
+ for (size_t i = 0; i < size(); i++)
{
- Parameter* p = parameters_[i];
+ Parameter* p = parameters_[i].get();
if (p->getName() == name) return *p;
}
throw ParameterNotFoundException("ParameterList::getParameter('name').", name);
}
/******************************************************************************/
+
+shared_ptr<Parameter>& ParameterList::getSharedParameter(const std::string& name) throw (ParameterNotFoundException)
+{
+ for (size_t i = 0; i < size(); i++)
+ {
+ shared_ptr<Parameter>& p = parameters_[i];
+ if (p->getName() == name)
+ return p;
+ }
+ throw ParameterNotFoundException("ParameterList::getSharedParameter('name').", name);
+}
+
+
+/******************************************************************************/
+
ParameterList ParameterList::subList(const std::vector<std::string>& names) const throw (ParameterNotFoundException)
{
ParameterList pl;
- for (unsigned int i = 0; i < names.size(); i++)
+ for (size_t i = 0; i < names.size(); i++)
{
Parameter param = getParameter(names[i]);
pl.addParameter(param);
@@ -131,6 +160,7 @@ ParameterList ParameterList::subList(const std::vector<std::string>& names) cons
}
/******************************************************************************/
+
ParameterList ParameterList::subList(const std::string& name) const throw (ParameterNotFoundException)
{
ParameterList pl;
@@ -140,33 +170,38 @@ ParameterList ParameterList::subList(const std::string& name) const throw (Param
}
/******************************************************************************/
+
ParameterList ParameterList::subList(const std::vector<size_t>& parameters) const
{
ParameterList pl;
- for (unsigned int i = 0; i < parameters.size(); i++)
+ for (size_t i = 0; i < parameters.size(); i++)
{
- if (parameters[i] < size()) pl.parameters_.push_back(dynamic_cast<Parameter*>(parameters_[parameters[i]]->clone()));
+ if (parameters[i] < size())
+ pl.parameters_.push_back(shared_ptr<Parameter>(parameters_[parameters[i]]->clone()));
}
return pl;
}
/******************************************************************************/
+
ParameterList ParameterList::subList(size_t parameter) const
{
ParameterList pl;
- if (parameter < size()) pl.parameters_.push_back(dynamic_cast<Parameter*>(parameters_[parameter]->clone()));
+ if (parameter < size())
+ pl.parameters_.push_back(shared_ptr<Parameter>(parameters_[parameter]->clone()));
return pl;
}
/******************************************************************************/
+
ParameterList ParameterList::getCommonParametersWith(const ParameterList& params) const
{
ParameterList pl;
- for (unsigned int i = 0; i < params.size(); i++)
+ for (size_t i = 0; i < params.size(); i++)
{
const Parameter& p = params[i];
if (hasParameter(p.getName()))
- pl.parameters_.push_back(dynamic_cast<Parameter*>(p.clone()));
+ pl.parameters_.push_back(shared_ptr<Parameter>(p.clone()));
// We use push_back instead of addParameter because we are sure the name is not duplicated.
}
@@ -178,7 +213,7 @@ ParameterList ParameterList::getCommonParametersWith(const ParameterList& params
std::vector<std::string> ParameterList::getParameterNames() const
{
vector<string> pNames(size());
- for (unsigned int i = 0; i < size(); i++)
+ for (size_t i = 0; i < size(); i++)
{
pNames[i] = parameters_[i]->getName();
}
@@ -190,7 +225,7 @@ std::vector<std::string> ParameterList::getParameterNames() const
vector<string> ParameterList::getMatchingParameterNames(const string& pattern) const
{
vector<string> pNames;
- for (unsigned int i = 0; i < size(); i++)
+ for (size_t i = 0; i < size(); i++)
{
string name = parameters_[i]->getName();
@@ -225,7 +260,8 @@ void ParameterList::addParameter(const Parameter& param) throw (ParameterExcepti
{
if (hasParameter(param.getName()))
throw ParameterException("ParameterList::addParameter. Parameter with name '" + param.getName() + "' already exists.", ¶m);
- parameters_.push_back(dynamic_cast<Parameter*>(param.clone()));
+ parameters_.push_back(shared_ptr<Parameter>(param.clone()));
+
}
/******************************************************************************/
@@ -234,28 +270,39 @@ void ParameterList::addParameter(Parameter* param) throw (ParameterException)
{
if (hasParameter(param->getName()))
throw ParameterException("ParameterList::addParameter. Parameter with name '" + param->getName() + "' already exists.", param);
- parameters_.push_back(param);
+ parameters_.push_back(shared_ptr<Parameter>(param));
}
/******************************************************************************/
+void ParameterList::shareParameter(const std::shared_ptr<Parameter>& param) throw (ParameterException)
+{
+ if (hasParameter(param->getName()))
+ setParameterValue(param->getName(), param->getValue());
+ else
+ parameters_.push_back(param);
+}
+
+
+/******************************************************************************/
+
void ParameterList::setParameter(size_t index, const Parameter& param) throw (IndexOutOfBoundsException)
{
if (index >= size()) throw IndexOutOfBoundsException("ParameterList::setParameter.", index, 0, size());
- delete parameters_[index];
- parameters_[index] = dynamic_cast<Parameter*>(param.clone());
+ parameters_[index] = shared_ptr<Parameter>(param.clone());
}
+
/******************************************************************************/
void ParameterList::includeParameters(const ParameterList& params)
{
- for (unsigned int i = 0; i < params.size(); i++)
+ for (size_t i = 0; i < params.size(); i++)
{
if (hasParameter(params[i].getName()))
setParameterValue(params[i].getName(), params[i].getValue());
else
- parameters_.push_back(dynamic_cast<Parameter*>(params[i].clone()));
+ parameters_.push_back(shared_ptr<Parameter>(params[i].clone()));
}
}
@@ -264,7 +311,7 @@ void ParameterList::includeParameters(const ParameterList& params)
void ParameterList::addParameters(const ParameterList& params)
throw (ParameterException)
{
- for (unsigned int i = 0; i < params.size(); i++)
+ for (size_t i = 0; i < params.size(); i++)
{
addParameter(params[i]);
}
@@ -272,6 +319,17 @@ throw (ParameterException)
/******************************************************************************/
+void ParameterList::shareParameters(const ParameterList& params)
+ throw (ParameterException)
+{
+ for (size_t i = 0; i < params.size(); i++)
+ {
+ shareParameter(params.getSharedParameter(i));
+ }
+}
+
+/******************************************************************************/
+
void ParameterList::setParameterValue(const string& name, double value)
throw (ParameterNotFoundException, ConstraintException)
{
@@ -285,15 +343,15 @@ void ParameterList::setAllParametersValues(const ParameterList& params)
throw (ParameterNotFoundException, ConstraintException)
{
// First we check if all values are correct:
- for (vector<Parameter*>::iterator it = parameters_.begin(); it < parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::iterator it = parameters_.begin(); it < parameters_.end(); it++)
{
const Parameter* p = ¶ms.getParameter((*it)->getName());
if ((*it)->hasConstraint() && !(*it)->getConstraint()->isCorrect(p->getValue()))
- throw ConstraintException("ParameterList::setParametersValues()", *it, p->getValue());
+ throw ConstraintException("ParameterList::setParametersValues()", (*it).get(), p->getValue());
}
// If all values are ok, we set them:
- for (vector<Parameter*>::iterator it = parameters_.begin(); it < parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::iterator it = parameters_.begin(); it < parameters_.end(); it++)
{
const Parameter* p = ¶ms.getParameter((*it)->getName());
(*it)->setValue(p->getValue());
@@ -305,7 +363,7 @@ throw (ParameterNotFoundException, ConstraintException)
void ParameterList::setParametersValues(const ParameterList& params)
{
// First we check if all values are correct:
- for (vector<Parameter*>::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
{
if (hasParameter((*it)->getName()))
{
@@ -317,7 +375,7 @@ void ParameterList::setParametersValues(const ParameterList& params)
// If all values are ok, we set them:
{
- for (vector<Parameter*>::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
{
if (hasParameter((*it)->getName()))
{
@@ -333,20 +391,20 @@ void ParameterList::setParametersValues(const ParameterList& params)
bool ParameterList::testParametersValues(const ParameterList& params) const
{
// First we check if all values are correct:
- for (vector<Parameter*>::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
{
if (hasParameter((*it)->getName()))
{
const Parameter* p = &getParameter((*it)->getName());
if (p->hasConstraint() && !p->getConstraint()->isCorrect((*it)->getValue()))
- throw ConstraintException("ParameterList::matchParametersValues()", p, (*it)->getValue());
+ throw ConstraintException("ParameterList::testParametersValues()", p, (*it)->getValue());
}
}
// If all values are ok, we test them:
bool ch = 0;
- for (vector<Parameter*>::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
{
if (hasParameter((*it)->getName()))
{
@@ -364,7 +422,7 @@ bool ParameterList::matchParametersValues(const ParameterList& params, vector<si
throw (ConstraintException)
{
// First we check if all values are correct:
- for (vector<Parameter*>::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
{
if (hasParameter((*it)->getName()))
{
@@ -378,7 +436,7 @@ throw (ConstraintException)
bool ch = 0;
size_t pos = 0;
- for (vector<Parameter*>::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
{
if (hasParameter((*it)->getName()))
{
@@ -399,7 +457,7 @@ throw (ConstraintException)
void ParameterList::setAllParameters(const ParameterList& params)
throw (ParameterNotFoundException)
{
- for (vector<Parameter*>::iterator it = parameters_.begin(); it < parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::iterator it = parameters_.begin(); it < parameters_.end(); it++)
{
const Parameter* p = ¶ms.getParameter((*it)->getName());
**it = *p;
@@ -410,7 +468,7 @@ throw (ParameterNotFoundException)
void ParameterList::setParameters(const ParameterList& params)
throw (ParameterNotFoundException)
{
- for (vector<Parameter*>::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
{
Parameter* p = &getParameter((*it)->getName());
*p = **it;
@@ -422,7 +480,7 @@ bool ParameterList::hasParameter(const std::string& name) const
{
for (unsigned int i = 0; i < size(); i++)
{
- const Parameter* p = parameters_[i];
+ const Parameter* p = parameters_[i].get();
if (p->getName() == name)
return true;
}
@@ -432,7 +490,7 @@ bool ParameterList::hasParameter(const std::string& name) const
/******************************************************************************/
void ParameterList::matchParameters(const ParameterList& params)
{
- for (vector<Parameter*>::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
+ for (vector<shared_ptr<Parameter> >::const_iterator it = params.parameters_.begin(); it < params.parameters_.end(); it++)
{
if (hasParameter((*it)->getName()))
{
@@ -447,10 +505,10 @@ void ParameterList::deleteParameter(const std::string& name) throw (ParameterNot
{
for (unsigned int i = 0; i < size(); i++)
{
- Parameter* p = parameters_[i];
+ Parameter* p = parameters_[i].get();
+
if (p->getName() == name)
{
- delete p;
parameters_.erase(parameters_.begin() + i);
return;
}
@@ -481,8 +539,8 @@ void ParameterList::deleteParameters(const std::vector<std::string>& names, bool
void ParameterList::deleteParameter(size_t index) throw (IndexOutOfBoundsException)
{
if (index >= size()) throw IndexOutOfBoundsException("ParameterList::deleteParameter.", index, 0, size());
- Parameter* p = parameters_[index];
- delete p;
+ // Parameter* p = parameters_[index].get();
+ // delete p;
parameters_.erase(parameters_.begin() + static_cast<ptrdiff_t>(index));
}
@@ -495,8 +553,8 @@ void ParameterList::deleteParameters(const std::vector<size_t>& indices) throw (
{
size_t index = *i;
if (index >= size()) throw IndexOutOfBoundsException("ParameterList::deleteParameter.", index, 0, size());
- Parameter* p = parameters_[index];
- delete p;
+// Parameter* p = parameters_[index].get();
+// delete p;
parameters_.erase(parameters_.begin() + static_cast<ptrdiff_t>(index));
}
}
@@ -528,10 +586,6 @@ void ParameterList::printParameters(OutputStream& out) const
/******************************************************************************/
void ParameterList::reset()
{
- for (unsigned int i = 0; i < size(); i++)
- {
- delete parameters_[i];
- }
parameters_.resize(0);
}
diff --git a/src/Bpp/Numeric/ParameterList.h b/src/Bpp/Numeric/ParameterList.h
index 57c6086..fb47c2d 100644
--- a/src/Bpp/Numeric/ParameterList.h
+++ b/src/Bpp/Numeric/ParameterList.h
@@ -62,7 +62,7 @@ class ParameterList :
public Clonable
{
private:
- std::vector<Parameter*> parameters_;
+ std::vector<std::shared_ptr<Parameter> > parameters_;
public:
/**
@@ -97,6 +97,13 @@ public:
virtual Parameter& operator[](size_t i) { return *parameters_[i]; }
/**
+ * @return The shared_ptr parameter at a given position.
+ * @warning No check is performed on the validity of the index given as input!
+ */
+ virtual const std::shared_ptr<Parameter>& getSharedParameter(size_t i) const { return parameters_[i]; }
+ virtual std::shared_ptr<Parameter>& getSharedParameter(size_t i) { return parameters_[i]; }
+
+ /**
* @brief Get the parameter with name <i>name</i>.
*
* @param name The name of the parameter to look for.
@@ -106,6 +113,15 @@ public:
virtual const Parameter& getParameter(const std::string& name) const throw (ParameterNotFoundException);
/**
+ * @brief Get the parameter with name <i>name</i> as a shared pointer.
+ *
+ * @param name The name of the parameter to look for.
+ * @return A const shared parameter toward the parameter with name <i>name</i>.
+ * @throw ParameterNotFoundException If no parameter with the given name is found.
+ */
+ virtual const std::shared_ptr<Parameter>& getSharedParameter(const std::string& name) const throw (ParameterNotFoundException);
+
+ /**
* @brief Get the value of the parameter with name <i>name</i>.
*
* @param name The name of the parameter to look for.
@@ -125,6 +141,15 @@ public:
virtual Parameter& getParameter(const std::string& name) throw (ParameterNotFoundException);
/**
+ * @brief Get the parameter with name <i>name</i> as a shared pointer.
+ *
+ * @param name The name of the parameter to look for.
+ * @return A shared parameter toward the parameter with name <i>name</i>.
+ * @throw ParameterNotFoundException If no parameter with the given name is found.
+ */
+ virtual std::shared_ptr<Parameter>& getSharedParameter(const std::string& name) throw (ParameterNotFoundException);
+
+ /**
* @brief Get given parameters as a sublist.
*
* @param names Name of the parameters to be included in the list.
@@ -199,25 +224,48 @@ public:
*
* @param param A ppointer toward the parameter to add to the list.
*/
+
virtual void addParameter(Parameter* param) throw (ParameterException);
/**
+ * @brief Share a parameter at the end of the list.
+ *
+ * @param param The shared_ptr parameter to add to the list.
+ */
+
+ virtual void shareParameter(const std::shared_ptr<Parameter>& param) throw (ParameterException);
+
+
+ /**
* @brief Change given parameter.
*
* @param index The position of the parameter to alter.
* @param param The parameter to add to the list.
* @throw IndexOutOfBoundsException if the index is not valid.
*/
+
virtual void setParameter(size_t index, const Parameter& param) throw (IndexOutOfBoundsException);
+// virtual void setParameter(size_t index, Parameter* param) throw (IndexOutOfBoundsException);
+
/**
* @brief Add new parameters at the end of the list.
*
- * @param params The parameter list containing the new paramters to add to the list.
+ * @param params The parameter list containing the new parameters to
+ * add to the list.
*/
virtual void addParameters(const ParameterList& params) throw (ParameterException);
/**
+ * @brief Share parameters with a given list. They are added the end of this list.
+ *
+ * @param params The parameter list containing the parameters to
+ * share with to the list.
+ */
+
+ virtual void shareParameters(const ParameterList& params) throw (ParameterException);
+
+ /**
* @brief Add parameters to the list. If the parameter already
* exists, only the value is updated, otherwise the new parameter is
* added at the end of the list.
diff --git a/src/Bpp/Numeric/ParametrizableCollection.h b/src/Bpp/Numeric/ParametrizableCollection.h
index e677d7b..d60d99b 100644
--- a/src/Bpp/Numeric/ParametrizableCollection.h
+++ b/src/Bpp/Numeric/ParametrizableCollection.h
@@ -245,6 +245,32 @@ namespace bpp
}
/**
+ * @brief Get the paramters of the Collection corresponding to an
+ * object from the set knowing its index.
+ *
+ * @param objectIndex Index of the object in the set.
+ * @return A ParameterList
+ */
+
+ ParameterList getParametersForObject(size_t objectIndex) const
+ {
+ ParameterList pl;
+ typename std::map<size_t, N*>::const_iterator it=objectsSet_.find(objectIndex);
+
+ if (it!=objectsSet_.end())
+ {
+ if (dynamic_cast<const ParameterAliasable*>(it->second)!=NULL)
+ pl = dynamic_cast<const ParameterAliasable*>(it->second)->getIndependentParameters();
+ else
+ pl = it->second->getParameters();
+
+ for (size_t i=0; i<pl.size();i++)
+ pl[i].setName(pl[i].getName()+"_"+TextTools::toString(objectIndex));
+ }
+ return pl;
+ }
+
+ /**
* @brief Add a new object to the set with a given number.
*
* @throw Exception if the number is already used. See replace function instead.
diff --git a/src/Bpp/Numeric/Prob/DiscreteDistribution.h b/src/Bpp/Numeric/Prob/DiscreteDistribution.h
index fa0fe1c..2c14d2e 100644
--- a/src/Bpp/Numeric/Prob/DiscreteDistribution.h
+++ b/src/Bpp/Numeric/Prob/DiscreteDistribution.h
@@ -73,9 +73,7 @@ namespace bpp
virtual ~DiscreteDistribution() {}
-#ifndef NO_VIRTUAL_COV
DiscreteDistribution* clone() const = 0;
-#endif
public:
diff --git a/src/Bpp/Numeric/Prob/GammaDiscreteDistribution.cpp b/src/Bpp/Numeric/Prob/GammaDiscreteDistribution.cpp
index 74ef1b8..f4ef78d 100644
--- a/src/Bpp/Numeric/Prob/GammaDiscreteDistribution.cpp
+++ b/src/Bpp/Numeric/Prob/GammaDiscreteDistribution.cpp
@@ -51,11 +51,12 @@ using namespace std;
/** Constructor: **************************************************************/
-GammaDiscreteDistribution::GammaDiscreteDistribution(size_t n, double alpha, double beta, double minimumAlpha, double minimumBeta) :
+GammaDiscreteDistribution::GammaDiscreteDistribution(size_t n, double alpha, double beta, double minimumAlpha, double minimumBeta, bool paramOffset, double offset) :
AbstractParameterAliasable("Gamma."),
AbstractDiscreteDistribution(n, "Gamma."),
alpha_(alpha),
beta_(beta),
+ offset_(offset),
ga1_(1)
{
// We use a lower bound of 0.0001 for alpha and beta to prohibe errors due to computer
@@ -65,9 +66,12 @@ GammaDiscreteDistribution::GammaDiscreteDistribution(size_t n, double alpha, dou
// algorithms.
addParameter_(new Parameter("Gamma.alpha", alpha, new IntervalConstraint(1, minimumAlpha, true), true));
addParameter_(new Parameter("Gamma.beta", beta, new IntervalConstraint(1, minimumBeta, true), true));
+ if (paramOffset)
+ addParameter_(new Parameter("Gamma.offset", offset));
+
ga1_ = exp(RandomTools::lnGamma(alpha_ + 1) - RandomTools::lnGamma(alpha_));
- intMinMax_.setLowerBound(0, true);
+ intMinMax_.setLowerBound(offset_, true);
discretize();
}
@@ -76,6 +80,7 @@ GammaDiscreteDistribution::GammaDiscreteDistribution(const GammaDiscreteDistribu
AbstractDiscreteDistribution(gdd),
alpha_(gdd.alpha_),
beta_(gdd.beta_),
+ offset_(gdd.offset_),
ga1_(gdd.ga1_)
{
}
@@ -86,6 +91,7 @@ GammaDiscreteDistribution& GammaDiscreteDistribution::operator=(const GammaDiscr
AbstractDiscreteDistribution::operator=(gdd);
alpha_=gdd.alpha_;
beta_=gdd.beta_;
+ offset_=gdd.offset_;
ga1_=gdd.ga1_;
return *this;
@@ -100,6 +106,8 @@ void GammaDiscreteDistribution::fireParameterChanged(const ParameterList& parame
AbstractDiscreteDistribution::fireParameterChanged(parameters);
alpha_ = getParameterValue("alpha");
beta_ = getParameterValue("beta");
+ if (hasParameter("offset"))
+ offset_ = getParameterValue("offset");
ga1_ = exp(RandomTools::lnGamma(alpha_ + 1) - RandomTools::lnGamma(alpha_));
discretize();
@@ -111,17 +119,17 @@ void GammaDiscreteDistribution::fireParameterChanged(const ParameterList& parame
double GammaDiscreteDistribution::qProb(double x) const
{
- return RandomTools::qGamma(x, alpha_, beta_);
+ return offset_ + RandomTools::qGamma(x, alpha_, beta_);
}
double GammaDiscreteDistribution::pProb(double x) const
{
- return RandomTools::pGamma(x, alpha_, beta_);
+ return RandomTools::pGamma(x-offset_, alpha_, beta_);
}
double GammaDiscreteDistribution::Expectation(double a) const
{
- return RandomTools::pGamma(a, alpha_ + 1, beta_) / beta_ * ga1_;
+ return RandomTools::pGamma(a-offset_, alpha_ + 1, beta_) / beta_ * ga1_ + (offset_ > 0 ? offset_ * RandomTools::pGamma(a - offset_, alpha_, beta_) : 0);
}
diff --git a/src/Bpp/Numeric/Prob/GammaDiscreteDistribution.h b/src/Bpp/Numeric/Prob/GammaDiscreteDistribution.h
index b8ed6d2..e84a0a6 100644
--- a/src/Bpp/Numeric/Prob/GammaDiscreteDistribution.h
+++ b/src/Bpp/Numeric/Prob/GammaDiscreteDistribution.h
@@ -48,7 +48,7 @@ namespace bpp
{
/**
- * @brief Discretized Gamma distribution.
+ * @brief Discretized Gamma distribution with an offset.
*
* @author Julien Dutheil, Laurent Guéguen, with original code from Tal Pupko and Ziheng Yang.
*/
@@ -60,6 +60,8 @@ namespace bpp
double alpha_, beta_;
+ double offset_;
+
// To prevent useless computations
double ga1_;
@@ -73,14 +75,20 @@ namespace bpp
* @param beta The beta parameter (rate)
* @param minimumAlpha The minimum allowed value for parameter alpha.
* @param minimumBeta The minimum allowed value for parameter beta.
+ * @param paramOffset bool if the distribution has an offset
+ * parameter (default: false).
+ * @param offset The distribution is offset + Gamma (default 0).
+ * P(X<x)=pGamma(x-offset,alpha,beta)
*
* The Parameters are: alpha and beta @f$ \in [minimumBound;\infty[ @f$.
* Small values of alpha and/or beta can lead to discretization issues.
*
+ *
* If @f$ alpha > 1 @f$, the minimum value of the distribution is
- * set to 1e-12, otherwise it is 0.
+ * set to offset+1e-12, otherwise it is offset.
*/
- GammaDiscreteDistribution(size_t n, double alpha = 1., double beta = 1., double minimumAlpha = 0.05, double minimumBeta = 0.05);
+
+ GammaDiscreteDistribution(size_t n, double alpha = 1., double beta = 1., double minimumAlpha = 0.05, double minimumBeta = 0.05, bool paramOffset = false, double offset = 0);
GammaDiscreteDistribution(const GammaDiscreteDistribution&);
@@ -99,7 +107,8 @@ namespace bpp
while (!intMinMax_.isCorrect(x))
x= RandomTools::randGamma(getParameterValue("alpha"),
getParameterValue("beta"));
- return x;
+
+ return x + offset_;
}
double qProb(double x) const;
diff --git a/src/Bpp/Numeric/Prob/MixtureOfDiscreteDistributions.h b/src/Bpp/Numeric/Prob/MixtureOfDiscreteDistributions.h
index 6b9397b..2b058e4 100644
--- a/src/Bpp/Numeric/Prob/MixtureOfDiscreteDistributions.h
+++ b/src/Bpp/Numeric/Prob/MixtureOfDiscreteDistributions.h
@@ -97,11 +97,7 @@ public:
MixtureOfDiscreteDistributions& operator=(const MixtureOfDiscreteDistributions& mdd);
-#if defined(NO_VIRTUAL_COV)
- Clonable* clone() const { return new MixtureOfDiscreteDistributions(*this); }
-#else
MixtureOfDiscreteDistributions* clone() const { return new MixtureOfDiscreteDistributions(*this); }
-#endif
public:
std::string getName() const {return "Mixture"; }
diff --git a/src/Bpp/Numeric/Prob/MultipleDiscreteDistribution.h b/src/Bpp/Numeric/Prob/MultipleDiscreteDistribution.h
index 55068bf..86fb4d8 100644
--- a/src/Bpp/Numeric/Prob/MultipleDiscreteDistribution.h
+++ b/src/Bpp/Numeric/Prob/MultipleDiscreteDistribution.h
@@ -73,9 +73,7 @@ namespace bpp
virtual ~MultipleDiscreteDistribution() {}
-#ifndef NO_VIRTUAL_COV
MultipleDiscreteDistribution * clone() const = 0;
-#endif
public:
diff --git a/src/Bpp/Numeric/Prob/Simplex.cpp b/src/Bpp/Numeric/Prob/Simplex.cpp
index b07591f..acc424f 100644
--- a/src/Bpp/Numeric/Prob/Simplex.cpp
+++ b/src/Bpp/Numeric/Prob/Simplex.cpp
@@ -170,8 +170,6 @@ void Simplex::fireParameterChanged(const ParameterList& parameters)
if (dim_==0)
return;
- AbstractParameterAliasable::fireParameterChanged(parameters);
-
double x = 1.0;
switch (method_)
{
@@ -285,10 +283,10 @@ void Simplex::setFrequencies(const std::vector<double>& probas)
if (t >= dim_)
break;
else
- i0 += vProb_[t];
+ i0 += probas[t];
t += (1 << (li2 - 1));
if (t < dim_)
- i1 += vProb_[t];
+ i1 += probas[t];
j++;
}
pl.addParameter(Parameter(getNamespace() + "theta" + TextTools::toString(i), i1 / (i0 + i1)));
diff --git a/src/Bpp/Numeric/Prob/Simplex.h b/src/Bpp/Numeric/Prob/Simplex.h
index cf93cb4..33763f3 100644
--- a/src/Bpp/Numeric/Prob/Simplex.h
+++ b/src/Bpp/Numeric/Prob/Simplex.h
@@ -57,7 +57,7 @@ namespace bpp
* If they are parametrized, the parameters are called \c "theta1",
* ..., \c "theta(n-1)".
*
- * Two ways of parametrization are available:
+ * Three ways of parametrization are available:
*
* Global ratio:
*
@@ -83,8 +83,9 @@ namespace bpp
* @f$i_k=a_k...a_1 at f$.
*
* Given @f$a_b...a_1 at f$ the writing of i in binary where @f$a_b=1 at f$,
- * we denote @f$1_i=\sum\{p_{j+1} \text{ such that } j_b=i_b=1i_{b-1}\}@f$ and
- * @f$0_i=\sum\{p_{j+1} \text{ such that } j_b=0i_{b-1}\}@f$, and then we define:
+ * we denote @f$1_i=\sum_j\{p_{j+1} \text{ such that }
+ * j_b=1i_{b-1}\}@f$ and @f$0_i=\sum_j\{p_{j+1} \text{ such that }
+ * j_b=0i_{b-1}\}@f$, and then we define:
*
*
* @f$\theta_i=\frac{1_i}{1_i+0_i}@f$
diff --git a/src/Bpp/Numeric/Random/RandomTools.cpp b/src/Bpp/Numeric/Random/RandomTools.cpp
index e470001..1ba3aba 100644
--- a/src/Bpp/Numeric/Random/RandomTools.cpp
+++ b/src/Bpp/Numeric/Random/RandomTools.cpp
@@ -228,25 +228,6 @@ double RandomTools::qNorm(double prob, double mu, double sigma)
return RandomTools::qNorm(prob) * sigma + mu;
}
-
-double RandomTools::lnGamma (double alpha)
-{
- double x = alpha, f = 0, z;
-
- if (x < 7)
- {
- f = 1; z = x - 1;
- while (++z < 7)
- f *= z;
- x = z; f = -log(f);
- }
- z = 1 / (x * x);
- return f + (x - 0.5) * log(x) - x + .918938533204673
- + (((-.000595238095238 * z + .000793650793651) * z - .002777777777778) * z
- + .083333333333333) / x;
-}
-
-
double RandomTools::incompleteGamma (double x, double alpha, double ln_gamma_alpha)
{
size_t i;
diff --git a/src/Bpp/Numeric/Random/RandomTools.h b/src/Bpp/Numeric/Random/RandomTools.h
index 77bb820..cf44569 100644
--- a/src/Bpp/Numeric/Random/RandomTools.h
+++ b/src/Bpp/Numeric/Random/RandomTools.h
@@ -194,7 +194,7 @@ namespace bpp
}
}
- template<class T>
+ template<class T>
static T pickOne(const std::vector<T>& v) throw (EmptyVectorException<T>) {
if (v.empty())
throw EmptyVectorException<T>("RandomTools::pickOne: input vector is empty", &v);
@@ -375,15 +375,10 @@ namespace bpp
/**
* @brief Computes \f$ln\left(\Gamma\left(\alpha\right)\right)\f$ given \f$\alpha\f$.
*
- * Returns ln(gamma(alpha)) for alpha>0, accurate to 10 decimal places.
- * Stirling's formula is used for the central polynomial part of the procedure.
- * Pike MC & Hill ID (1966) Algorithm 291: Logarithm of the gamma function.
- * Communications of the Association for Computing Machinery, 9:684
- *
* @param alpha Alpha parameter.
* @return \f$ln\left(\Gamma\left(\alpha\right)\right)\f$
*/
- static double lnGamma (double alpha);
+ static double lnGamma(double alpha) { return std::lgamma(alpha); }
/**
* @brief Returns the incomplete gamma ratio I(x,alpha).
@@ -477,11 +472,12 @@ namespace bpp
* @{
*/
+
/**
* @brief Normal cumulative function.
*
* Returns Prob{x<=z} where x ~ N(0,1)
-
+ *
* @param z the value.
* @return The corresponding probability.
*/
@@ -509,8 +505,7 @@ namespace bpp
* @param alpha, beta Alpha and Beta parameters.
* @return \f$ln\left(Beta\left(\alpha,\beta\right)\right)\f$
*/
-
- static double lnBeta (double alpha, double beta);
+ static double lnBeta(double alpha, double beta);
/**
* @brief Returns the regularized incomplete beta function
diff --git a/src/Bpp/Numeric/Range.h b/src/Bpp/Numeric/Range.h
index bb4a669..109d271 100644
--- a/src/Bpp/Numeric/Range.h
+++ b/src/Bpp/Numeric/Range.h
@@ -247,6 +247,11 @@ template<class T> class RangeCollection {
virtual size_t size() const = 0;
/**
+ * @return The number of positions in the collection.
+ */
+ virtual size_t totalLength() const = 0;
+
+ /**
* @return The ith range in the collection.
*/
virtual const Range<T>& getRange(size_t i) const = 0;
@@ -350,6 +355,17 @@ template<class T> class RangeSet:
bool isEmpty() const { return ranges_.size() == 0; }
size_t size() const { return ranges_.size(); }
+
+ /**
+ * @return The total length of the range set. Overlapping positions will be counted several times.
+ */
+ size_t totalLength() const {
+ size_t tot = 0;
+ for (typename std::set< Range<T>* >::const_iterator it = ranges_.begin(); it != ranges_.end(); ++it) {
+ tot += (**it).length();
+ }
+ return tot;
+ }
const Range<T>& getRange(size_t i) const {
typename std::set< Range<T>* >::const_iterator it = ranges_.begin();
@@ -482,6 +498,14 @@ template<class T> class MultiRange:
size_t size() const { return ranges_.size(); }
+ size_t totalLength() const {
+ size_t tot = 0;
+ for (typename std::vector< Range<T>* >::const_iterator it = ranges_.begin(); it != ranges_.end(); ++it) {
+ tot += (**it).length();
+ }
+ return tot;
+ }
+
const Range<T>& getRange(size_t i) const { return *ranges_[i]; }
void clear() {
diff --git a/src/Bpp/Numeric/Stat/ContingencyTableTest.h b/src/Bpp/Numeric/Stat/ContingencyTableTest.h
index 84111c9..a545023 100644
--- a/src/Bpp/Numeric/Stat/ContingencyTableTest.h
+++ b/src/Bpp/Numeric/Stat/ContingencyTableTest.h
@@ -74,12 +74,7 @@ class ContingencyTableTest:
ContingencyTableTest(const std::vector< std::vector<size_t> >& table, unsigned int nbPermutations = 0, bool warn = true);
virtual ~ContingencyTableTest() {}
-#ifndef NO_VIRTUAL_COV
- ContingencyTableTest*
-#else
- Clonable*
-#endif
- clone() const { return new ContingencyTableTest(*this); }
+ ContingencyTableTest* clone() const { return new ContingencyTableTest(*this); }
public:
std::string getName() const { return "Test on contingency table."; }
diff --git a/src/Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.h b/src/Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.h
index ccf7fce..8b2d205 100644
--- a/src/Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.h
+++ b/src/Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.h
@@ -45,6 +45,8 @@
#include "DualityDiagram.h"
namespace bpp
+{
+
/**
* @brief This class allows to perform a correspondence analysis.
*
@@ -53,7 +55,7 @@ namespace bpp
*
* The code of this class is deeply inspired from the R code of the dudi.coa function available in the ade4 package.
*/
-{
+
class CorrespondenceAnalysis:
public DualityDiagram
{
@@ -79,12 +81,7 @@ public:
virtual ~CorrespondenceAnalysis() {}
-#ifndef NO_VIRTUAL_COV
- CorrespondenceAnalysis*
-#else
- Clonable*
-#endif
- clone() const { return new CorrespondenceAnalysis(*this); }
+ CorrespondenceAnalysis* clone() const { return new CorrespondenceAnalysis(*this); }
public:
double getSumOfAllValues() const throw (Exception) { return n_; }
diff --git a/src/Bpp/Numeric/Stat/Mva/DualityDiagram.h b/src/Bpp/Numeric/Stat/Mva/DualityDiagram.h
index 4900561..a9a872f 100644
--- a/src/Bpp/Numeric/Stat/Mva/DualityDiagram.h
+++ b/src/Bpp/Numeric/Stat/Mva/DualityDiagram.h
@@ -106,12 +106,7 @@ public:
virtual ~DualityDiagram();
-#ifndef NO_VIRTUAL_COV
- DualityDiagram*
-#else
- Clonable*
-#endif
- clone() const { return new DualityDiagram(*this); }
+ DualityDiagram* clone() const { return new DualityDiagram(*this); }
private:
void check_(
diff --git a/src/Bpp/Numeric/Table.h b/src/Bpp/Numeric/Table.h
new file mode 100644
index 0000000..1bbd2f8
--- /dev/null
+++ b/src/Bpp/Numeric/Table.h
@@ -0,0 +1,1222 @@
+//
+// File: Table.h
+// Created by: Laurent Guéguen
+// Created on: dimanche 2 avril 2017, à 22h 59
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide classes
+ for numerical calculus.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#ifndef _TABLE_H_
+#define _TABLE_H_
+
+#include "VectorTools.h"
+#include "TableExceptions.h"
+#include "../Clonable.h"
+
+// From the STL:
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+
+
+namespace bpp
+{
+/**
+ * @brief This class corresponds to a 'dataset', <i>i.e.</i> a table
+ * with data by rows and variable by columns.
+ *
+ * Data are stored as T objects, by column.
+ */
+
+ template<class T>
+ class Table :
+ public Clonable
+ {
+ protected:
+ size_t nRow_, nCol_;
+ std::vector< std::vector<T> > data_;
+ std::vector<std::string> rowNames_;
+ std::vector<std::string> colNames_;
+
+ public:
+ /**
+ * @brief Build a new void Table object with nRow rows and nCol columns.
+ *
+ * @param nRow The number of rows of the Table.
+ * @param nCol The number of columns of the Table.
+ */
+
+ Table(size_t nRow, size_t nCol) :
+ nRow_(nRow),
+ nCol_(nCol),
+ data_(nCol),
+ rowNames_(),
+ colNames_()
+ {
+ for (size_t i = 0; i < nCol; i++)
+ {
+ data_[i].resize(nRow);
+ }
+ }
+
+ /**
+ * @brief Build a new void Table object with named columns.
+ *
+ * @param colNames The names of the columns of the Table.
+ * @throw DuplicatedTableColumnNameException If colnames contains identical names.
+ */
+
+ Table(const std::vector<std::string>& colNames) throw (DuplicatedTableColumnNameException) :
+ nRow_(0),
+ nCol_(colNames.size()),
+ data_(colNames.size()),
+ rowNames_(),
+ colNames_()
+ {
+ setColumnNames(colNames); // May throw an exception.
+ }
+
+
+ Table(const Table& table) :
+ nRow_(table.nRow_),
+ nCol_(table.nCol_),
+ data_(table.data_),
+ rowNames_(table.rowNames_),
+ colNames_(table.colNames_)
+ {
+ }
+
+ Table(const std::vector<std::vector<T> >& vt) :
+ nRow_(vt.size()==0?0:vt[0].size()),
+ nCol_(vt.size()),
+ data_(vt),
+ rowNames_(),
+ colNames_()
+ {}
+
+ Table& operator=(const Table& table)
+ {
+ nRow_ = table.nRow_;
+ nCol_ = table.nCol_;
+ data_ = table.data_;
+ rowNames_ = table.rowNames_;
+ colNames_ = table.colNames_;
+ return *this;
+ }
+
+ Table& operator=(const std::vector<std::vector<T> >& vt)
+ {
+ nCol_ = vt.size();
+ if (vt.size()==0)
+ {
+ nRow_ = 0;
+ data_.clear();
+ }
+ else
+ {
+ nRow_=vt[0].size();
+ data_=vt;
+ }
+
+ rowNames_.clear();
+ colNames_.clear();
+ return *this;
+ }
+
+ Table* clone() const { return new Table(*this); }
+
+ virtual ~Table() {}
+
+ public:
+ /**
+ * @return The data.
+ *
+ */
+
+ const std::vector< std::vector<T> >& getData() const
+ {
+ return data_;
+ }
+
+
+ /**
+ * @return The element at a given position.
+ * @param rowIndex Row number.
+ * @param colIndex Column number.
+ * @throw IndexOutOfBoundsException If one of the index is greater or equal to the corresponding number of columns/rows.
+ */
+
+ T& operator()(size_t rowIndex, size_t colIndex) throw (IndexOutOfBoundsException)
+ {
+ if (colIndex >= nCol_)
+ throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", colIndex, 0, nCol_ - 1);
+ if (rowIndex >= data_[colIndex].size())
+ throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", rowIndex, 0, data_[colIndex].size() - 1);
+ return data_[colIndex][rowIndex];
+ }
+
+ /**
+ * @return The element at a given position.
+ * @param rowIndex Row number.
+ * @param colIndex Column number.
+ * @throw IndexOutOfBoundsException If one of the index is greater or equal to the corresponding number of columns/rows.
+ */
+
+ const T& operator()(size_t rowIndex, size_t colIndex) const throw (IndexOutOfBoundsException)
+ {
+ if (colIndex >= nCol_)
+ throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", colIndex, 0, nCol_ - 1);
+ if (rowIndex >= data_[colIndex].size())
+ throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", rowIndex, 0, data_[colIndex].size() - 1);
+ return data_[colIndex][rowIndex];
+ }
+
+ /**
+ * @return The element at a given position.
+ * @param rowName Row name.
+ * @param colName Column name.
+ * @throw NoTableRowNamesException If the table does not have names associated to rows.
+ * @throw NoTableColumnNamesException If the table does not have names associated to columns.
+ * @throw TableNameNotFoundException If one of rowName or colName do not match existing names.
+ */
+
+ T& operator()(const std::string& rowName, const std::string& colName)
+ throw (NoTableRowNamesException, NoTableColumnNamesException, TableNameNotFoundException)
+ {
+ if (rowNames_.size() == 0)
+ throw NoTableRowNamesException("Table::operator(const string &, const string &).");
+ if (colNames_.size() == 0)
+ throw NoTableColumnNamesException("Table::operator(const string &, const string &).");
+ try
+ {
+ size_t rowIndex = VectorTools::which(rowNames_, rowName);
+ size_t colIndex = VectorTools::which(colNames_, colName);
+ return (*this)(rowIndex, colIndex);
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
+ }
+ }
+
+ /**
+ * @return The element at a given position.
+ * @param rowName Row name.
+ * @param colName Column name.
+ * @throw NoTableRowNamesException If the table does not have names associated to rows.
+ * @throw NoTableColumnNamesException If the table does not have names associated to columns.
+ * @throw TableNameNotFoundException If one of rowName or colName do
+ * not match existing names.
+ */
+ const T& operator()(const std::string& rowName, const std::string& colName) const
+ throw (NoTableRowNamesException, NoTableColumnNamesException, TableNameNotFoundException)
+ {
+ if (rowNames_.size() == 0)
+ throw NoTableRowNamesException("Table::operator(const string &, const string &).");
+ if (colNames_.size() == 0)
+ throw NoTableColumnNamesException("Table::operator(const string &, const string &).");
+ try
+ {
+ size_t rowIndex = VectorTools::which(rowNames_, rowName);
+ size_t colIndex = VectorTools::which(colNames_, colName);
+ return (*this)(rowIndex, colIndex);
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
+ }
+ }
+
+
+
+ /**
+ * @return The element at a given position.
+ * @param rowName Row name.
+ * @param colIndex Column number.
+ * @throw NoTableRowNamesException If the table does not have names associated to rows.
+ * @throw IndexOutOfBoundsException If the index is greater or equal to the number of columns.
+ * @throw TableNameNotFoundException If rowName do not match existing names.
+ */
+
+ T& operator()(const std::string& rowName, size_t colIndex)
+ throw (NoTableRowNamesException, TableNameNotFoundException, IndexOutOfBoundsException)
+ {
+ if (rowNames_.size() == 0)
+ throw NoTableRowNamesException("Table::operator(const string &, size_t).");
+ if (colIndex >= nCol_)
+ throw IndexOutOfBoundsException("Table::operator(const string &, size_t).", colIndex, 0, nCol_ - 1);
+ try
+ {
+ size_t rowIndex = VectorTools::which(rowNames_, rowName);
+ return (*this)(rowIndex, colIndex);
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableNameNotFoundException("Table::operator(const string &, size_t).", *ex.getElement());
+ }
+ }
+
+
+ /**
+ * @return The element at a given position.
+ * @param rowName Row name.
+ * @param colIndex Column number.
+ * @throw NoTableRowNamesException If the table does not have names associated to rows.
+ * @throw IndexOutOfBoundsException If the index is greater or equal to the number of columns.
+ * @throw TableNameNotFoundException If rowName do not match existing names.
+ */
+
+ const T& operator()(const std::string& rowName, size_t colIndex) const
+ throw (NoTableRowNamesException, TableNameNotFoundException, IndexOutOfBoundsException)
+ {
+ if (rowNames_.size() == 0)
+ throw NoTableRowNamesException("Table::operator(const string &, size_t).");
+ if (colIndex >= nCol_)
+ throw IndexOutOfBoundsException("Table::operator(const string &, size_t).", colIndex, 0, nCol_ - 1);
+ try
+ {
+ size_t rowIndex = VectorTools::which(rowNames_, rowName);
+ return (*this)(rowIndex, colIndex);
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableNameNotFoundException("Table::operator(const string &, size_t).", *ex.getElement());
+ }
+ }
+
+
+ /**
+ * @return The element at a given position.
+ * @param rowIndex Row number.
+ * @param colName Column name.
+ * @throw IndexOutOfBoundsException If the index is greater or equal to the number of rows.
+ * @throw NoTableColumnNamesException If the table does not have names associated to columns.
+ * @throw TableNameNotFoundException If colName do not match existing names.
+ */
+
+ T& operator()(size_t rowIndex, const std::string& colName)
+ throw (IndexOutOfBoundsException, NoTableColumnNamesException, TableNameNotFoundException)
+ {
+ if (colNames_.size() == 0)
+ throw NoTableColumnNamesException("Table::operator(size_t, const string &).");
+ try
+ {
+ size_t colIndex = VectorTools::which(colNames_, colName);
+ if (rowIndex >= data_[colIndex].size())
+ throw IndexOutOfBoundsException("Table::operator(size_t, const string &).", rowIndex, 0, data_[colIndex].size() - 1);
+ return (*this)(rowIndex, colIndex);
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
+ }
+ }
+
+
+ /**
+ * @return The element at a given position.
+ * @param rowIndex Row number.
+ * @param colName Column name.
+ * @throw IndexOutOfBoundsException If the index is greater or equal to the number of rows.
+ * @throw NoTableColumnNamesException If the table does not have names associated to columns.
+ * @throw TableNameNotFoundException If colName do not match existing names.
+ */
+
+ const T& operator()(size_t rowIndex, const std::string& colName) const
+ throw (IndexOutOfBoundsException, NoTableColumnNamesException, TableNameNotFoundException)
+ {
+ if (colNames_.size() == 0)
+ throw NoTableColumnNamesException("Table::operator(size_t, const string &).");
+ try
+ {
+ size_t colIndex = VectorTools::which(colNames_, colName);
+ if (rowIndex >= data_[colIndex].size())
+ throw IndexOutOfBoundsException("Table::operator(size_t, const string &).", rowIndex, 0, data_[colIndex].size() - 1);
+ return (*this)(rowIndex, colIndex);
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
+ }
+ }
+
+ /**
+ * @name Work on columns.
+ *
+ * @{
+ */
+
+ /**
+ * @return The number of columns in this table.
+ */
+ size_t getNumberOfColumns() const { return nCol_; }
+
+ /**
+ * @brief Set the column names of this table.
+ *
+ * @param colNames The row names.
+ * @throw DimensionException If the number of names do not match the number of columns in the table.
+ * @throw DuplicatedTableColumnNameException If names are not unique.
+ */
+ void setColumnNames(const std::vector<std::string>& colNames) throw (DimensionException, DuplicatedTableColumnNameException)
+ {
+ if (!VectorTools::isUnique(colNames))
+ throw DuplicatedTableColumnNameException("Table::setColumnNames(...). Column names must be unique.");
+ if (colNames.size() != nCol_)
+ throw DimensionException("Table::setColumnNames.", colNames.size(), nCol_);
+ else
+
+ colNames_ = colNames;
+ }
+
+ /**
+ * @brief Get the column names of this table.
+ *
+ * @return The column names of this table.
+ * @throw NoTableColumnNamesException If no column names are associated to this table.
+ */
+
+ const std::vector<std::string>& getColumnNames() const throw (NoTableColumnNamesException)
+ {
+ if (colNames_.size() == 0)
+ throw NoTableColumnNamesException("Table::getColumnNames().");
+ return colNames_;
+ }
+
+ std::vector<std::string>& getColumnNames() throw (NoTableColumnNamesException)
+ {
+ if (colNames_.size() == 0)
+ throw NoTableColumnNamesException("Table::getColumnNames().");
+ return colNames_;
+ }
+
+ /**
+ * @brief Get a given column name.
+ *
+ * @param index The index of the column.
+ * @return The column name associated to the given column.
+ * @throw NoTableColumnNamesException If no column names are associated to this table.
+ * @throw IndexOutOfBoundsException If index is >= number of columns.
+ */
+ std::string getColumnName(size_t index) const throw (NoTableColumnNamesException, IndexOutOfBoundsException)
+ {
+ if (colNames_.size() ==0)
+ throw NoTableColumnNamesException("Table::getColumnName(size_t).");
+ if (index >= nCol_)
+ throw IndexOutOfBoundsException("Table::getColumnName(size_t).", index, 0, nCol_ - 1);
+ return colNames_[index];
+ }
+
+
+ /**
+ * @return true If column names are associated to this table.
+ */
+ bool hasColumnNames() const { return colNames_.size() != 0; }
+
+ /**
+ * @return The values in the given column.
+ * @param index The index of the column.
+ * @throw IndexOutOfBoundsException If index is >= number of columns.
+ */
+ std::vector<T>& getColumn(size_t index)
+ {
+ if (index >= nCol_)
+ throw IndexOutOfBoundsException("Table::getColumn(size_t).", index, 0, nCol_ - 1);
+ return data_[index];
+ }
+
+ /**
+ * @return The values in the given column.
+ * @param index The index of the column.
+ * @throw IndexOutOfBoundsException If index is >= number of columns.
+ */
+ const std::vector<T>& getColumn(size_t index) const
+ {
+ if (index >= nCol_)
+ throw IndexOutOfBoundsException("Table::getColumn(size_t).", index, 0, nCol_ - 1);
+ return data_[index];
+ }
+
+
+ /**
+ * @return The values in the given column.
+ * @param colName The name of the column.
+ * @throw NoTableColumnNamesException If no column names are associated to this table.
+ * @throw TableColumnNameNotFoundException If colName do not match existing column names.
+ */
+ std::vector<T>& getColumn(const std::string& colName) throw (NoTableColumnNamesException, TableColumnNameNotFoundException)
+ {
+ if (colNames_.size() == 0)
+ throw NoTableColumnNamesException("Table::getColumn(const string &).");
+ try
+ {
+ size_t colIndex = VectorTools::which(colNames_, colName);
+ return data_[colIndex];
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableColumnNameNotFoundException("Table::getColumn(const string &).", colName);
+ }
+ }
+
+ /**
+ * @return The values in the given column.
+ * @param colName The name of the column.
+ * @throw NoTableColumnNamesException If no column names are associated to this table.
+ * @throw TableColumnNameNotFoundException If colName do not match existing column names.
+ */
+ const std::vector<T>& getColumn(const std::string& colName) const throw (NoTableColumnNamesException, TableColumnNameNotFoundException)
+ {
+ if (colNames_.size() == 0)
+ throw NoTableColumnNamesException("Table::getColumn(const string &).");
+ try
+ {
+ size_t colIndex = VectorTools::which(colNames_, colName);
+ return data_[colIndex];
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableColumnNameNotFoundException("Table::getColumn(const string &).", colName);
+ }
+ }
+
+
+ /**
+ * @brief Tell is a given column exists.
+ *
+ * @param colName The name of the column to look for.
+ * @return true if the column was found, false if not or if there are no column names.
+ */
+ bool hasColumn(const std::string& colName) const
+ {
+ if (colNames_.size() == 0)
+ return false;
+ for (size_t i = 0; i < colNames_.size(); i++)
+ {
+ if ((colNames_)[i] == colName)
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * @brief Delete the given column.
+ *
+ * @param index The index of the column.
+ * @throw IndexOutOfBoundsException If index is >= number of columns.
+ */
+ void deleteColumn(size_t index) throw (IndexOutOfBoundsException)
+ {
+ if (index >= nCol_)
+ throw IndexOutOfBoundsException("Table::deleteColumn(size_t).", index, 0, nCol_ - 1);
+ data_.erase(data_.begin() + (size_t)index);
+ if (colNames_.size()!=0)
+ colNames_.erase(colNames_.begin() + (size_t)(index));
+ nCol_--;
+ }
+
+/**
+ * @brief Delete the given column.
+ *
+ * @param colName The name of the column.
+ * @throw NoTableColumnNamesException If no column names are associated to this table.
+ * @throw TableColumnNameNotFoundException If colName do not match existing column names.
+ */
+ void deleteColumn(const std::string& colName) throw (NoTableColumnNamesException, TableColumnNameNotFoundException)
+ {
+ if ((colNames_.size()==0))
+ throw NoTableColumnNamesException("Table::deleteColumn(const string &).");
+ try
+ {
+ size_t colIndex = VectorTools::which(colNames_, colName);
+ data_.erase(data_.begin() + (size_t)(colIndex));
+ colNames_.erase(colNames_.begin() + (size_t)(colIndex));
+ nCol_--;
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableColumnNameNotFoundException("Table::deleteColumn(const string &).", colName);
+ }
+ }
+
+
+ /**
+ * @brief Add a new column.
+ *
+ * @param newColumn The new column values.
+ * @param pos The position optional (default : -1 for nb columns)
+ * @throw DimensionException If the number of values does not match the number of rows.
+ * @throw TableColumnNamesException If the table has row names.
+ */
+
+ void addColumn(const std::vector<T>& newColumn, int pos=-1) throw (DimensionException, TableColumnNamesException)
+ {
+ if (pos>(int)nCol_)
+ throw DimensionException("Table::addColumn.", pos, nCol_);
+ if (pos==-1)
+ pos=nCol_;
+
+ if (colNames_.size())
+ throw TableColumnNamesException("Table::addColumn. Table has column names.");
+ if (newColumn.size() != nRow_)
+ throw DimensionException("Table::addColumn.", newColumn.size(), nRow_);
+
+ data_.insert(data_.begin()+pos, newColumn);
+ nCol_++;
+ }
+
+ /**
+ * @brief Add a new column.
+ *
+ * @param colName The name of the column.
+ * @param newColumn The new column values.
+ * @param pos The position optional (default : -1 for nb columns)
+ * @throw DimensionException If the number of values does not match the number of rows.
+ * @throw NoTableColumnNamesException If the table does not have row names.
+ * @throw DuplicatedTableColumnNameException If colName is already used.
+ */
+
+ void addColumn(const std::string& colName, const std::vector<T>& newColumn, int pos=-1) throw (DimensionException, NoTableColumnNamesException, DuplicatedTableColumnNameException)
+ {
+ if (pos>(int)nCol_)
+ throw DimensionException("Table::addColumn.", pos, nCol_);
+ if (pos==-1)
+ pos=nCol_;
+
+ if ((colNames_.size()==0))
+ {
+ if (nCol_ == 0)
+ colNames_ = new std::vector<std::string>();
+ else
+ throw NoTableColumnNamesException("Table::addColumn. Table has column names.");
+ }
+ if (newColumn.size() != nRow_)
+ throw DimensionException("Table::addColumn.", newColumn.size(), nRow_);
+ if (nCol_ > 0 && find(colNames_.begin(), colNames_.end(), colName) != colNames_.end())
+ throw DuplicatedTableColumnNameException("Table::addColumn(const string &, const std::vector<string> &). Column names must be unique.");
+
+ colNames_.insert(colNames_.begin()+pos,colName);
+ data_.insert(data_.begin()+pos, newColumn);
+ nCol_++;
+ }
+
+ /**
+ * @brief Add a new column
+ *
+ * @param stream the input stream
+ * @param sep The row delimiter
+ * @param pos The position optional (default : nb cols)
+ * @param rowCol the indice of row where colnames are, starting
+ * from 0 (default -1 means no such column)
+ */
+
+ void addColumn(std::string& st, const std::string& sep = "\t", int pos=-1, int rowCol = -1)
+ {
+ if (pos>(int)nCol_)
+ throw DimensionException("Table::addColumn.", pos, nCol_);
+ if (pos==-1)
+ pos=nCol_;
+
+ StringTokenizer stok(st, sep, false, true);
+ std::vector<std::string> row(stok.getTokens().begin(), stok.getTokens().end());
+
+ if (row.size()!=nRow_+(rowCol>=0)?1:0)
+ throw BadIntegerException("Table::addColumn. Bad number of rows: ", row.size());
+
+ std::vector<T> newColumn;
+
+ for (size_t i=0; i<row.size(); i++)
+ {
+ if (i==rowCol)
+ {
+ std::string colName=row[i];
+ if (find(colNames_.begin(), colNames_.end(), colName) != colNames_.end())
+ throw DuplicatedTableColumnNameException("Table::addColumn(const std::vector<string> &). Column names must be unique.");
+
+ colNames_.insert(colNames_.begin()+(size_t)pos,colName);
+ }
+ else
+ {
+ std::stringstream ss(row[i]);
+ T t;
+ ss >> t;
+ newColumn.push_back(t);
+ }
+ }
+ data_.insert(data_.begin()+pos, newColumn);
+
+ nCol_++;
+ }
+
+
+ /**
+ * @brief Set a new column.
+ *
+ * @param newColumn The new column values.
+ * @param pos The position
+ * @throw DimensionException If the number of values does not match the number of rows.
+ * @throw TableColumnNamesException If the table has row names.
+ */
+
+ void setColumn(const std::vector<T>& newColumn, size_t pos) throw (DimensionException, TableColumnNamesException)
+ {
+ if (pos>=(int)nCol_)
+ throw DimensionException("Table::setColumn.", pos, nCol_);
+
+ if (newColumn.size() != nRow_)
+ throw DimensionException("Table::setColumn.", newColumn.size(), nRow_);
+
+ data_[pos]=newColumn;
+ }
+
+ /**
+ * @brief Set a new column.
+ *
+ * @param colName The name of the column.
+ * @param newColumn The new column values.
+ * @param pos The position
+ * @throw DimensionException If the number of values does not match the number of rows.
+ * @throw NoTableColumnNamesException If the table does not have row names.
+ * @throw DuplicatedTableColumnNameException If colName is already used.
+ */
+ void setColumn(const std::string& colName, const std::vector<T>& newColumn, size_t pos) throw (DimensionException, NoTableColumnNamesException, DuplicatedTableColumnNameException)
+ {
+ if (pos>=nCol_)
+ throw DimensionException("Table::setColumn.", pos, nCol_);
+
+ if (colNames_.size()==0)
+ throw NoTableColumnNamesException("Table::setColumn. Table has column names.");
+
+ if (newColumn.size() != nRow_)
+ throw DimensionException("Table::setColumn.", newColumn.size(), nRow_);
+
+ if (find(colNames_.begin(), colNames_.end(), colName) != colNames_.end() &&
+ find(colNames_.begin(), colNames_.end(), colName) != colNames_.begin()+pos)
+ throw DuplicatedTableColumnNameException("Table::setColumn(const string &, const std::vector<T> &, size_t). Column names must be unique.");
+
+ colNames_[pos]=colName;
+ data_[pos]=newColumn;
+ }
+
+ /** @} */
+
+ /**
+ * @name Work on rows.
+ *
+ * @{
+ */
+
+ /**
+ * @return The number of rows in this table.
+ */
+ size_t getNumberOfRows() const { return nRow_; }
+
+ /**
+ * @brief Set the row names of this table.
+ *
+ * @param rowNames The row names.
+ * @throw DimensionException If the number of names do not match the number of rows in the table.
+ * @throw DuplicatedTableRowNameException If names are not unique.
+ */
+ void setRowNames(const std::vector<std::string>& rowNames) throw (DimensionException, DuplicatedTableRowNameException)
+ {
+ if (!VectorTools::isUnique(rowNames))
+ {
+ throw DuplicatedTableRowNameException("Table::setRowNames(...). Row names must be unique.");
+ }
+ if (rowNames.size() != nRow_)
+ throw DimensionException("Table::setRowNames.", rowNames.size(), nRow_);
+ else
+ {
+ rowNames_ = rowNames;
+ }
+ }
+
+
+ /**
+ * @brief Get the row names of this table.
+ *
+ * @return The row names of this table.
+ * @throw NoTableRowNamesException If no row names are associated to this table.
+ */
+
+ std::vector<std::string> getRowNames() throw (NoTableRowNamesException)
+ {
+ if (rowNames_.size() == 0)
+ throw NoTableRowNamesException("Table::getRowNames().");
+ return rowNames_;
+ }
+
+ const std::vector<std::string>& getRowNames() const throw (NoTableRowNamesException)
+ {
+ if (rowNames_.size() == 0)
+ throw NoTableRowNamesException("Table::getRowNames().");
+ return rowNames_;
+ }
+
+
+ /**
+ * @brief Tell is a given row exists.
+ *
+ * @param rowName The name of the row to look for.
+ * @return true if the row was found, false if not or if there are no row names.
+ */
+ bool hasRow(const std::string& rowName) const
+ {
+ if (rowNames_.size() == 0)
+ return false;
+ for (size_t i = 0; i < rowNames_.size(); i++)
+ {
+ if ((rowNames_)[i] == rowName)
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * @brief Get a given row name.
+ *
+ * @param index The index of the row.
+ * @return The row name associated to the given row.
+ * @throw NoTableRowNamesException If no row names are associated to this table.
+ * @throw IndexOutOfBoundsException If index is >= number of rows.
+ */
+ std::string getRowName(size_t index) const throw (NoTableRowNamesException, IndexOutOfBoundsException)
+ {
+ if (rowNames_.size() == 0)
+ throw NoTableRowNamesException("Table::getRowName(size_t).");
+ if (index >= nRow_)
+ throw IndexOutOfBoundsException("Table::getRowName(size_t).", index, 0, nRow_ - 1);
+ return (rowNames_)[index];
+ }
+
+
+ /**
+ * @return true If row names are associated to this table.
+ */
+ bool hasRowNames() const { return rowNames_.size() != 0; }
+
+ /**
+ * @return A vector which contains a copy in the given row.
+ * @param index The index of the row.
+ * @throw IndexOutOfBoundsException If index is >= number of rows.
+ */
+ std::vector<T> getRow(size_t index) const throw (IndexOutOfBoundsException)
+ {
+ if (index >= nRow_)
+ throw IndexOutOfBoundsException("Table::getRow(size_t).", index, 0, nRow_ - 1);
+ std::vector<T> row;
+ for (size_t i = 0; i < nCol_; i++)
+ {
+ row.push_back(data_[i][index]);
+ }
+ return row;
+ }
+
+
+ /**
+ * @return A vector which contains a copy in the given row.
+ * @param rowName The name of the row.
+ * @throw NoTableRowNamesException If no row names are associated to this table.
+ * @throw TableRowNameNotFoundException If rowName do not match existing row names.
+ */
+ std::vector<T> getRow(const std::string& rowName) const throw (NoTableRowNamesException, TableRowNameNotFoundException)
+ {
+ if ((rowNames_.size()==0))
+ throw NoTableRowNamesException("Table::getRow(const string &).");
+ try
+ {
+ size_t rowIndex = VectorTools::which(rowNames_, rowName);
+ std::vector<T> row;
+ for (size_t i = 0; i < nCol_; i++)
+ {
+ row.push_back(data_[i][rowIndex]);
+ }
+ return row;
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableRowNameNotFoundException("Table::getRow(const string &).", rowName);
+ }
+ }
+
+
+ /**
+ * @brief Delete the given row.
+ *
+ * @param index The index of the row.
+ * @throw IndexOutOfBoundsException If index is >= number of row.
+ */
+ void deleteRow(size_t index) throw (IndexOutOfBoundsException)
+ {
+ for (size_t j = 0; j < nCol_; j++)
+ {
+ std::vector<T>* column = &data_[j];
+ if (index >= column->size())
+ throw IndexOutOfBoundsException("Table::deleteRow(size_t).", index, 0, column->size() - 1);
+ column->erase(column->begin() + index);
+ }
+ if (rowNames_.size()!=0)
+ rowNames_.erase(rowNames_.begin() + index);
+ nRow_--;
+ }
+
+ /**
+ * @brief Delete the given rows.
+ *
+ * @param index The index of the first row.
+ * @param len the number of rows to delete
+ * @throw IndexOutOfBoundsException If index is >= number of row.
+ */
+
+ void deleteRows(size_t index, size_t len) throw (IndexOutOfBoundsException)
+ {
+ for (size_t j = 0; j < nCol_; j++)
+ {
+ std::vector<T>* column = &data_[j];
+ if (index >= column->size())
+ throw IndexOutOfBoundsException("Table::deleteRow(size_t).", index, 0, column->size() - 1);
+ column->erase(column->begin() + index, column->begin() + index + len);
+ }
+ if (rowNames_.size()!=0)
+ rowNames_.erase(rowNames_.begin() + index, rowNames_.begin() + index + len);
+ nRow_--;
+ }
+
+
+ /**
+ * @brief Delete the given row.
+ *
+ * @param rowName The name of the row.
+ * @throw NoTableRowNamesException If no row names are associated to this table.
+ * @throw TableRowNameNotFoundException If rowName do not match existing column names.
+ */
+ void deleteRow(const std::string& rowName) throw (NoTableRowNamesException, TableRowNameNotFoundException)
+ {
+ if ((rowNames_.size()==0))
+ throw NoTableRowNamesException("Table::deleteRow(const string &).");
+ try
+ {
+ size_t rowIndex = VectorTools::which(rowNames_, rowName);
+ for (size_t j = 0; j < nCol_; j++)
+ {
+ std::vector<T>* column = &data_[j];
+ column->erase(column->begin() + rowIndex);
+ }
+ rowNames_.erase(rowNames_.begin() + rowIndex);
+ nRow_--;
+ }
+ catch (ElementNotFoundException<std::string>& ex)
+ {
+ throw TableRowNameNotFoundException("Table::deleteRow(const string &).", rowName);
+ }
+ }
+
+
+ /**
+ * @brief Add a new row.
+ *
+ * @param newRow The new row values.
+ * @param pos The position optional (default : -1 for nb rows)
+ */
+ void addRow(const std::vector<T>& newRow, int pos=-1)
+ {
+ if (pos>(int)nRow_)
+ throw DimensionException("Table::addRow.", pos, nRow_);
+
+ if (pos==-1)
+ pos=nRow_;
+
+ if (rowNames_.size()!=0)
+ throw TableRowNamesException("Table::addRow. Table has row names.");
+ if (newRow.size() != nCol_)
+ throw DimensionException("Table::addRow.", newRow.size(), nCol_);
+ for (size_t j = 0; j < nCol_; j++)
+ {
+ data_[j].insert(data_[j].begin()+(size_t)pos, newRow[j]);
+ }
+ nRow_++;
+ }
+
+ /**
+ * @brief Add a new row at a given position
+ *
+ * @param rowName The name of the row.
+ * @param newRow The new row values.
+ * @param pos The position optional (default : -1 for nb rows)
+ */
+
+ void addRow(const std::string& rowName, const std::vector<T>& newRow, int pos=-1)
+ {
+ if (pos>(int)nRow_)
+ throw DimensionException("Table::addRow.", pos, nRow_);
+ if (pos==-1)
+ pos=nRow_;
+
+ if ((rowNames_.size()==0))
+ {
+ if (nRow_ == 0)
+ rowNames_ = new std::vector<std::string>();
+ else
+ throw NoTableRowNamesException("Table::addRow. Table has row names.");
+ }
+ if (newRow.size() != nCol_)
+ throw DimensionException("Table::addRow.", newRow.size(), nCol_);
+ if (nRow_ > 0 && find(rowNames_.begin(), rowNames_.end(), rowName) != rowNames_.end())
+ throw DuplicatedTableRowNameException("Table::addRow(const string &, const std::vector<string> &). Row names must be unique.");
+ rowNames_.insert(rowNames_.begin()+(size_t)pos,rowName);
+ for (size_t j = 0; j < nCol_; j++)
+ {
+ data_[j].insert(data_[j].begin()+(size_t)pos, newRow[j]);
+ }
+ nRow_++;
+ }
+
+ /**
+ * @brief Add a new row.
+ *
+ * @param stream the input stream
+ * @param sep The column delimiter
+ * @param pos The position optional (default : nb rows)
+ * @param rowCol the indice of column where rownames are, starting
+ * from 0 (default -1 means no such column)
+ */
+
+ void addRow(std::string& st, const std::string& sep = "\t", int pos=-1, int rowCol = -1)
+ {
+ if (pos>(int)nRow_)
+ throw DimensionException("Table::addRow.", pos, nRow_);
+ if (pos==-1)
+ pos=nRow_;
+
+ StringTokenizer stok(st, sep, false, true);
+ std::vector<std::string> row(stok.getTokens().begin(), stok.getTokens().end());
+
+ if (row.size()!=nCol_+(rowCol>=0)?1:0)
+ throw BadIntegerException("Table::addRow. Bad number of columns: ", row.size());
+
+ size_t id=0;
+
+ for (size_t i=0; i<row.size(); i++)
+ {
+ if (i==rowCol)
+ {
+ std::string rowName=row[i];
+ if (find(rowNames_.begin(), rowNames_.end(), rowName) != rowNames_.end())
+ throw DuplicatedTableRowNameException("Table::addRow(const std::vector<string> &). Row names must be unique.");
+
+ rowNames_.insert(rowNames_.begin()+(size_t)pos,rowName);
+ }
+ else
+ {
+ std::stringstream ss(row[i]);
+ T t;
+ ss >> t;
+ data_[id].insert(data_[id].begin()+(size_t)pos,t);
+ id++;
+ }
+ }
+ nRow_++;
+ }
+
+
+ /** @} */
+
+ public:
+ /**
+ * @brief Read a table form a stream in CSV-like
+ *
+ * By default, if the first line as one column less than the second one,
+ * the first line is taken as column names, and the first column as row names.
+ * Otherwise, no column names and no row names are specified, unless
+ * explicitely precised by the user.
+ * Note: if byRow=false, exchange row and column roles.
+ *
+ * @param in The input stream.
+ * @param byRow Tell if the table is filled by rows
+ * @param sep The line delimiter.
+ * @param header Tell if the first line must be used for names,
+ * otherwise use default.
+ * @param names Use a column as rowNames (or a row as columnNames). If positive, use the specified column to compute rownames, otherwise use default;
+ * @return A pointer toward a new Table object.
+ */
+
+ static Table<T>* read(std::istream& in, bool byRow, const std::string& sep = "\t", bool header = true, int names = -1)
+ {
+ std::string firstLine = FileTools::getNextLine(in);
+ StringTokenizer st1(firstLine, sep, false, true);
+ std::vector<std::string> row1(st1.getTokens().begin(), st1.getTokens().end());
+ size_t nCol = row1.size();
+ Table<T>* dt;
+
+ if (header)
+ {
+ // Use first line as header.
+ if (byRow)
+ {
+ dt = new Table<T>(0,nCol);
+ dt->setColumnNames(row1);
+ }
+ else
+ {
+ dt = new Table<T>(nCol,0);
+ dt->setRowNames(row1);
+ }
+ }
+ else
+ {
+ if (byRow)
+ {
+ dt = new Table<T>(0,nCol-(names>=0?1:0));
+ dt->addRow(firstLine, sep, names);
+ }
+ else
+ {
+ dt = new Table<T>(nCol-(names>=0?1:0),0);
+ dt->addColumn(firstLine, sep, names);
+ }
+ }
+
+ // Now read each line:
+ std::string line = FileTools::getNextLine(in);
+
+ while (!TextTools::isEmpty(line))
+ {
+ if (byRow)
+ dt->addRow(line, sep, names);
+ else
+ dt->addColumn(line, sep, names);
+
+ line = FileTools::getNextLine(in);
+ }
+ return dt;
+ }
+
+
+ /**
+ * @brief Write a Table object to stream in CVS-like format.
+ *
+ * @param data The table to write.
+ * @param out The output stream.
+ * @param byRow Tell if the table is written by rows.
+ * @param sep The column delimiter.
+ * @param alignHeaders If true, add a delimiter before the first column header if there is row names.
+ */
+ static void write(const Table& data, std::ostream& out, bool byRow, const std::string& sep = "\t", bool alignHeaders = false)
+ {
+ size_t n = (byRow?data.getNumberOfColumns():data.getNumberOfRows());
+ if (n == 0)
+ return;
+ size_t m = (byRow?data.getNumberOfRows():data.getNumberOfColumns());
+
+ bool frontNames=((byRow && data.hasRowNames()) || (!byRow && data.hasColumnNames()));
+
+ if (byRow && data.hasColumnNames() || (!byRow && data.hasRowNames()))
+ { // Write header
+ std::vector<std::string> names = (byRow?data.getColumnNames():data.getRowNames());
+
+ if (alignHeaders && frontNames)
+ out << sep;
+ out << names[0];
+ for (size_t i = 1; i < n; i++)
+ {
+ out << sep << names[i];
+ }
+ out << std::endl;
+ }
+
+ // now write each row (or column):
+
+ for (size_t i = 0; i < m; i++)
+ {
+ if (frontNames){
+ out << (byRow?data.getRowName(i):data.getColumnName(i)) << sep;
+ }
+
+ out << (byRow?data(i, 0):data(0, i));
+ for (size_t j = 1; j < n; j++)
+ {
+ out << sep << (byRow?data(i, j):data(j, i));
+ }
+ out << std::endl;
+ }
+ }
+
+ static void write(const Table& data, bpp::OutputStream& out, bool byRow, const std::string& sep = "\t", bool alignHeaders = false)
+ {
+ size_t n = (byRow?data.getNumberOfColumns():data.getNumberOfRows());
+ if (n == 0)
+ return;
+ size_t m = (byRow?data.getNumberOfRows():data.getNumberOfColumns());
+
+ bool frontNames=((byRow && data.hasRowNames()) || (!byRow && data.hasColumnNames()));
+
+ if (byRow && data.hasColumnNames() || (!byRow && data.hasRowNames()))
+ { // Write header
+ std::vector<std::string> names = (byRow?data.getColumnNames():data.getRowNames());
+
+ if (alignHeaders && frontNames)
+ out << sep;
+ out << names[0];
+ for (size_t i = 1; i < n; i++)
+ {
+ out << sep << names[i];
+ }
+ out.endLine();
+ }
+
+ // now write each row (or column):
+
+ for (size_t i = 0; i < m; i++)
+ {
+ if (frontNames)
+ out << (byRow?data.getRowName(i):data.getColumnName(i) << sep);
+
+ out << (byRow?data(i, 0):data(0, i));
+ for (size_t j = 1; j < n; j++)
+ {
+ out << sep << byRow?data(i, j):data(j, i);
+ }
+ out.endLine();
+ }
+ }
+
+ };
+} // end of namespace bpp.
+
+#endif // _Table_H_
+
diff --git a/src/Bpp/Numeric/TableExceptions.h b/src/Bpp/Numeric/TableExceptions.h
new file mode 100644
index 0000000..51c586c
--- /dev/null
+++ b/src/Bpp/Numeric/TableExceptions.h
@@ -0,0 +1,175 @@
+//
+// File: DataTableExceptions.h
+// Created by: Julien Dutheil
+// Created on: Tue Nov 2005 14:10
+// from file DataTable.h
+//
+
+/*
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide classes
+ for numerical calculus.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#ifndef _TABLEEXCEPTIONS_H_
+#define _TABLEEXCEPTIONS_H_
+
+//#include "VectorTools.h"
+
+// From Utils:
+#include "../Exceptions.h"
+#include "../Text/TextTools.h"
+
+// From the STL:
+#include <string>
+
+namespace bpp
+{
+
+/**
+ * @brief Exception thrown when a given name is not found is a DataTable object.
+ */
+ class TableNameNotFoundException:
+ public Exception
+ {
+ protected:
+ std::string _name;
+
+ public:
+ TableNameNotFoundException(const std::string & text, const std::string & name) :
+ Exception("TableNameNotFoundException: " + name + ". " + text), _name(name) {}
+ virtual ~TableNameNotFoundException() throw() {}
+
+ public:
+ std::string getName() const { return _name; }
+ };
+
+/**
+ * @brief Exception thrown when a given row name is not found is a DataTable object.
+ */
+ class TableRowNameNotFoundException:
+ public TableNameNotFoundException
+ {
+ public:
+ TableRowNameNotFoundException(const std::string & text, const std::string & name) :
+ TableNameNotFoundException("TableRowNameNotFoundException: " + name + ". " + text, name) {}
+ virtual ~TableRowNameNotFoundException() throw() {}
+ };
+
+/**
+ * @brief Exception thrown when a given column name is not found is a DataTable object.
+ */
+ class TableColumnNameNotFoundException:
+ public TableNameNotFoundException
+ {
+ public:
+ TableColumnNameNotFoundException(const std::string & text, const std::string & name) :
+ TableNameNotFoundException("TableColumnNameNotFoundException: " + name + ". " + text, name) {}
+ virtual ~TableColumnNameNotFoundException() throw() {}
+ };
+
+/**
+ * @brief Exception thrown when trying to retrieve a row by its name
+ * and no row names have been specified.
+ */
+ class NoTableRowNamesException:
+ public Exception
+ {
+ public:
+ NoTableRowNamesException(const std::string & text) :
+ Exception("NoTableRowNamesException: "+text) {}
+ virtual ~NoTableRowNamesException() throw() {}
+ };
+
+/**
+ * @brief Exception thrown when trying to retrieve a column by its name
+ * and no column names have been specified.
+ */
+ class NoTableColumnNamesException:
+ public Exception
+ {
+ public:
+ NoTableColumnNamesException(const std::string & text) :
+ Exception("NoTableColumnNamesException: "+text) {}
+ virtual ~NoTableColumnNamesException() throw() {}
+ };
+
+/**
+ * @brief General exception class dealing with row names.
+ */
+ class TableRowNamesException:
+ public Exception
+ {
+ public:
+ TableRowNamesException(const std::string & text) :
+ Exception("TableRowNamesException: "+text) {}
+ virtual ~TableRowNamesException() throw() {}
+ };
+
+/**
+ * @brief General exception class dealing with column names.
+ */
+ class TableColumnNamesException:
+ public Exception
+ {
+ public:
+ TableColumnNamesException(const std::string & text) :
+ Exception("TableColumnNamesException: "+text) {}
+ virtual ~TableColumnNamesException() throw() {}
+ };
+
+/**
+ * @brief Exception thrown when attempting to duplicate a row name.
+ */
+ class DuplicatedTableRowNameException:
+ public Exception
+ {
+ public:
+ DuplicatedTableRowNameException(const std::string & text) :
+ Exception("DuplicatedTableRowNameException: "+text) {}
+ virtual ~DuplicatedTableRowNameException() throw() {}
+ };
+
+/**
+ * @brief Excpetion thrown when attempting to duplicate a column name.
+ */
+ class DuplicatedTableColumnNameException:
+ public Exception
+ {
+ public:
+ DuplicatedTableColumnNameException(const std::string & text) :
+ Exception("DuplicatedTableColumnNameException: "+text) {}
+ virtual ~DuplicatedTableColumnNameException() throw() {}
+ };
+
+} //end of namespace bpp.
+
+#endif //_TABLEEXCEPTIONS_H_
+
diff --git a/src/Bpp/Numeric/VectorTools.h b/src/Bpp/Numeric/VectorTools.h
index 8967d26..8bc62df 100644
--- a/src/Bpp/Numeric/VectorTools.h
+++ b/src/Bpp/Numeric/VectorTools.h
@@ -79,6 +79,11 @@ typedef std::vector<Vint> VVint;
typedef std::vector<VVint> VVVint;
typedef std::vector<VVVint> VVVVint;
+typedef std::vector<unsigned int> Vuint;
+typedef std::vector<Vint> VVuint;
+typedef std::vector<VVint> VVVuint;
+typedef std::vector<VVVint> VVVVuint;
+
/**
* @name Element-wise operations.
* @{
@@ -286,6 +291,14 @@ void operator/=(std::vector<T>& v1, const std::vector<T>& v2) throw (DimensionEx
}
}
+template<class T, class C>
+void operator&=(std::vector<T>& v1, const C& c)
+{
+ for (size_t i = 0; i < v1.size(); i++)
+ {
+ v1[i] = c;
+ }
+}
template<class T, class C>
void operator+=(std::vector<T>& v1, const C& c)
@@ -660,6 +673,9 @@ public:
static T logSumExp(const std::vector<T>& v1)
{
T M = max(v1);
+ if (std::isinf(M))
+ return M;
+
T x = std::exp(v1[0] - M);
for (size_t i = 1; i < v1.size(); i++)
{
@@ -684,6 +700,9 @@ public:
size = v1.size();
T M = max(v1);
+ if (std::isinf(M))
+ throw BadNumberException("VectorTools::logSumExp", M);
+
T x = v2[0] * std::exp(v1[0] - M);
for (size_t i = 1; i < size; i++)
{
@@ -701,6 +720,9 @@ public:
static T logMeanExp(const std::vector<T>& v1)
{
T M = max(v1);
+ if (std::isinf(M))
+ return M;
+
T x = std::exp(v1[0] - M);
for (size_t i = 1; i < v1.size(); i++)
{
@@ -719,6 +741,9 @@ public:
static T sumExp(const std::vector<T>& v1)
{
T M = max(v1);
+ if (std::isinf(M))
+ return (M<0?0:M);
+
T x = std::exp(v1[0] - M);
for (size_t i = 1; i < v1.size(); i++)
{
@@ -738,11 +763,14 @@ public:
{
size_t size;
if (v1.size() != v2.size())
- throw DimensionException("VectorTools::logsumexp", v1.size(), v2.size());
+ throw DimensionException("VectorTools::sumExp", v1.size(), v2.size());
else
size = v1.size();
T M = max(v1);
+ if (std::isinf(M))
+ throw BadNumberException("VectorTools::sumExp", M);
+
T x = v2[0] * std::exp(v1[0] - M);
for (size_t i = 1; i < size; i++)
{
@@ -757,13 +785,21 @@ public:
*
* @{
*/
+
template<class T>
- static std::vector<double> log(const std::vector<T>& v1)
+ static std::vector<T> log(const std::vector<T>& v1)
{
- std::vector<double> v2(v1.size());
- for (size_t i = 0; i < v2.size(); i++) { v2[i] = std::log(v1[i]); }
+ std::vector<T> v2(v1.size());
+ for (size_t i = 0; i < v2.size(); i++) { v2[i] = VectorTools::log(v1[i]); }
return v2;
}
+
+ template<class T>
+ static double log(const T& x)
+ {
+ return std::log(x);
+ }
+
template<class T>
static std::vector<double> log(const std::vector<T>& v1, double base)
{
@@ -773,10 +809,16 @@ public:
}
template<class T>
- static std::vector<double> exp(const std::vector<T>& v1)
+ static double exp(const T& x)
{
- std::vector<double> v2(v1.size());
- for (size_t i = 0; i < v2.size(); i++) { v2[i] = std::exp(v1[i]); }
+ return std::exp(x);
+ }
+
+ template<class T>
+ static std::vector<T> exp(const std::vector<T>& v1)
+ {
+ std::vector<T> v2(v1.size());
+ for (size_t i = 0; i < v2.size(); i++) { v2[i] = VectorTools::exp(v1[i]); }
return v2;
}
@@ -867,6 +909,31 @@ public:
out.endLine();
}
+ template<class T>
+ static void printRange(const std::vector<T>& v1, OutputStream& out = * ApplicationTools::message, const std::string& delim = ",", const std::string& rangeDelim = "-")
+ {
+ size_t vs=v1.size();
+
+ for (size_t i = 0; i < vs; i++)
+ {
+ out << v1[i];
+ size_t j=i+1;
+
+ while (j<vs)
+ if (v1[j]==v1[j-1]+1)
+ j++;
+ else
+ break;
+
+ if (j>i+2)
+ out << rangeDelim << v1[j-1];
+ i=j-1;
+ if (i<vs-1)
+ out << delim;
+ }
+ }
+
+
/**
* @brief Print a std::vector to a stream in R format
* @param v1 A std::vector.
@@ -898,7 +965,7 @@ public:
{
if (v1.size() != v2.size())
{
- throw DimensionException("VectorFunctions::scalar", v1.size(), v2.size());
+ throw DimensionException("VectorTools::scalar", v1.size(), v2.size());
}
OutputType result = 0;
for (size_t i = 0; i < v1.size(); i++)
@@ -928,11 +995,11 @@ public:
{
if (v1.size() != w.size())
{
- throw DimensionException("VectorFunctions::scalar", v1.size(), w.size());
+ throw DimensionException("VectorTools::scalar", v1.size(), w.size());
}
if (v2.size() != w.size())
{
- throw DimensionException("VectorFunctions::scalar", v2.size(), w.size());
+ throw DimensionException("VectorTools::scalar", v2.size(), w.size());
}
OutputType result = 0;
for (size_t i = 0; i < v1.size(); i++)
@@ -992,7 +1059,7 @@ public:
{
if (v1.size() != w.size())
{
- throw DimensionException("VectorFunctions::norm", v1.size(), w.size());
+ throw DimensionException("VectorTools::norm", v1.size(), w.size());
}
OutputType result = 0;
for (size_t i = 0; i < v1.size(); i++)
@@ -1047,7 +1114,7 @@ public:
template<class T>
static T min(const std::vector<T>& v) throw (EmptyVectorException<T> )
{
- if (v.size() == 0) throw EmptyVectorException<T>("VectorFunctions::min()", &v);
+ if (v.size() == 0) throw EmptyVectorException<T>("VectorTools::min()", &v);
T mini = v[0];
for (size_t i = 1; i < v.size(); i++)
{
@@ -1068,7 +1135,7 @@ public:
template<class T>
static T max(const std::vector<T>& v) throw (EmptyVectorException<T> )
{
- if (v.size() == 0) throw EmptyVectorException<T>("VectorFuntions::max()", &v);
+ if (v.size() == 0) throw EmptyVectorException<T>("VectorTools::max()", &v);
T maxi = v[0];
for (size_t i = 1; i < v.size(); i++)
{
@@ -1117,7 +1184,7 @@ public:
template<class T>
static size_t whichMin(const std::vector<T>& v) throw (EmptyVectorException<T> )
{
- if (v.size() == 0) throw EmptyVectorException<T>("VectorFunctions::whichMin()", &v);
+ if (v.size() == 0) throw EmptyVectorException<T>("VectorTools::whichMin()", &v);
T mini = v[0];
size_t pos = 0;
for (size_t i = 1; i < v.size(); i++)
diff --git a/src/Bpp/Text/KeyvalTools.cpp b/src/Bpp/Text/KeyvalTools.cpp
index 396db5e..d6fe39b 100644
--- a/src/Bpp/Text/KeyvalTools.cpp
+++ b/src/Bpp/Text/KeyvalTools.cpp
@@ -57,7 +57,7 @@ void KeyvalTools::singleKeyval(const std::string& desc, std::string& key, std::s
void KeyvalTools::multipleKeyvals(const std::string& desc, std::map<std::string,std::string>& keyvals, const std::string& split, bool nested) throw (KeyvalException)
{
- auto_ptr<StringTokenizer> st;
+ unique_ptr<StringTokenizer> st;
if (nested)
st.reset(new NestedStringTokenizer(desc, "(", ")", split));
else
@@ -95,6 +95,80 @@ void KeyvalTools::multipleKeyvals(const std::string& desc, std::map<std::string,
}
}
+std::string KeyvalTools::changeKeyvals(const std::string& desc, const std::map<std::string, std::string>& newkeyvals, const std::string& split, bool nested) throw (KeyvalException)
+{
+ string::size_type begin = desc.find_first_of("(");
+ string::size_type end = desc.find_last_of(")");
+
+ if (begin == string::npos && end == string::npos)
+ {
+ //Empty procedure:
+ return desc;
+ }
+ if (begin == string::npos && end != string::npos)
+ throw KeyvalException("Bad keyval procedure, missing opening parenthesis.");
+ if (begin == string::npos && end != string::npos)
+ throw KeyvalException("Bad keyval procedure, missing closing parenthesis.");
+
+ if (!TextTools::isEmpty(desc.substr(end + 1)))
+ throw KeyvalException("Bad keyval procedure, extra characters after closing parenthesis: " + desc.substr(end + 1));
+ //Get the procedure name (without leading spaces):
+
+ string newDesc= TextTools::removeFirstWhiteSpaces(desc.substr(0, begin))+"(";
+
+ string desckv=desc.substr(begin + 1, end - begin - 1);
+
+ unique_ptr<StringTokenizer> st;
+ if (nested)
+ st.reset(new NestedStringTokenizer(desckv, "(", ")", split));
+ else
+ st.reset(new StringTokenizer(desckv, split));
+ string key, val;
+ vector<string> tokens;
+ //Check tokens:
+ string token;
+
+ while (st->hasMoreToken())
+ {
+ token = st->nextToken();
+ if (token == "=")
+ {
+ //We need to merge the next token with the last one:
+ if (tokens.size() == 0)
+ throw KeyvalException("Invalid syntax, found '=' without argument name.");
+ if (!st->hasMoreToken())
+ throw KeyvalException("Invalid syntax, found '=' without argument value.");
+ string nextToken = st->nextToken();
+ if (nextToken == "=")
+ throw KeyvalException("Invalid syntax, found a double '='.");
+ tokens[tokens.size() - 1] += "=" + nextToken;
+ }
+ else
+ {
+ tokens.push_back(token);
+ }
+ }
+
+ for (vector<string>::iterator it = tokens.begin(); it != tokens.end(); it++)
+ {
+ singleKeyval(*it, key, val);
+ key=TextTools::removeSurroundingWhiteSpaces(key);
+ if (it!=tokens.begin())
+ newDesc+=split;
+
+ map<string, string>::const_iterator iter=newkeyvals.find(key);
+
+ if (iter!=newkeyvals.end())
+ newDesc+=key+"="+iter->second;
+ else
+ newDesc+=*it;
+ }
+
+ newDesc+=")";
+
+ return newDesc;
+}
+
void KeyvalTools::parseProcedure(const std::string& desc, std::string& name, std::map<std::string, std::string>& args) throw (KeyvalException)
{
string::size_type begin = desc.find_first_of("(");
diff --git a/src/Bpp/Text/KeyvalTools.h b/src/Bpp/Text/KeyvalTools.h
index 4a078c5..e5100c2 100644
--- a/src/Bpp/Text/KeyvalTools.h
+++ b/src/Bpp/Text/KeyvalTools.h
@@ -87,7 +87,8 @@ class KeyvalTools
* @param split [in] The delimiter. Default is '=' but ':' can be used.
* @throw KeyvalException If the syntax describing the keyval is not correct.
*/
- static void singleKeyval(const std::string& desc, std::string& key, std::string& val, const std::string& split = "=") throw (KeyvalException);
+
+ static void singleKeyval(const std::string& desc, std::string& key, std::string& val, const std::string& split = "=") throw (KeyvalException);
/**
* @brief Split a string into several keys and corresponding values (General purpose function).
@@ -98,8 +99,28 @@ class KeyvalTools
* @param nested [in] Tell if nested keyval procedures are expected.
* @throw KeyvalException If the syntax describing the keyval is not correct.
*/
+
static void multipleKeyvals(const std::string& desc, std::map<std::string, std::string>& keyvals, const std::string& split = ",", bool nested = true) throw (KeyvalException);
+ /**
+ * @brief Change several keys to new corresponding values (General
+ * purpose function).
+ *
+ * @param desc [in] A string descibing the keyval, with format
+ * key1=val1,key2=val2,etc (space are considered normal character,
+ * that's up to you to deal with that afterwards!).
+ * @param newkeyvals [in] contains the text of the keys to be changed
+ * and their new corresponding values. If a key is not in desc, it
+ * is not added.
+ * @param split [in] The keyval delimiter. The default is a coma,
+ * but a space character can be used for instance.
+ * @param nested [in] Tell if nested keyval procedures are expected.
+ * @return the string with the changed values.
+ * @throw KeyvalException If the syntax describing the keyval is not correct.
+ */
+
+ static std::string changeKeyvals(const std::string& desc, const std::map<std::string, std::string>& newkeyvals, const std::string& split = ",", bool nested = true) throw (KeyvalException);
+
/**
* @brief Parse (not recursively) a procedure string.
*
diff --git a/src/Bpp/Text/StringTokenizer.cpp b/src/Bpp/Text/StringTokenizer.cpp
index ac2caa3..5e06960 100644
--- a/src/Bpp/Text/StringTokenizer.cpp
+++ b/src/Bpp/Text/StringTokenizer.cpp
@@ -95,12 +95,6 @@ StringTokenizer::StringTokenizer(const std::string& s, const std::string& delimi
}
}
-const std::string& StringTokenizer::nextToken() throw (Exception)
-{
- if (!hasMoreToken()) throw Exception("No more token in tokenizer.");
- return tokens_[currentPosition_++];
-}
-
void StringTokenizer::removeEmptyTokens()
{
for (size_t i = tokens_.size(); i > currentPosition_; i--)
diff --git a/src/Bpp/Text/StringTokenizer.h b/src/Bpp/Text/StringTokenizer.h
index a7061e0..374a9a2 100644
--- a/src/Bpp/Text/StringTokenizer.h
+++ b/src/Bpp/Text/StringTokenizer.h
@@ -91,7 +91,11 @@ namespace bpp
*
* @return The next token if there is one.
*/
- const std::string& nextToken() throw (Exception);
+ const std::string& nextToken() throw (Exception)
+ {
+ if (!hasMoreToken()) throw Exception("No more token in tokenizer.");
+ return tokens_[currentPosition_++];
+ }
/**
* @brief Tell if some tokens are still available.
diff --git a/src/Bpp/Text/TextTools.cpp b/src/Bpp/Text/TextTools.cpp
index b531b8a..1afb81b 100644
--- a/src/Bpp/Text/TextTools.cpp
+++ b/src/Bpp/Text/TextTools.cpp
@@ -38,6 +38,7 @@
*/
#include "TextTools.h"
+#include "../Exceptions.h"
using namespace bpp;
@@ -299,7 +300,7 @@ std::string TextTools::toString(double d, int precision)
/******************************************************************************/
-int TextTools::toInt(const std::string& s, char scientificNotation) throw (Exception)
+int TextTools::toInt(const std::string& s, char scientificNotation)
{
if (!isDecimalInteger(s, scientificNotation)) throw Exception("TextTools::toInt(). Invalid number specification: " + s);
istringstream iss(s);
@@ -310,7 +311,7 @@ int TextTools::toInt(const std::string& s, char scientificNotation) throw (Excep
/******************************************************************************/
-double TextTools::toDouble(const std::string& s, char dec, char scientificNotation) throw (Exception)
+double TextTools::toDouble(const std::string& s, char dec, char scientificNotation)
{
if (!isDecimalNumber(s, dec, scientificNotation)) throw Exception("TextTools::toDouble(). Invalid number specification: " + s);
istringstream iss(s);
@@ -326,7 +327,7 @@ std::string TextTools::resizeRight(const std::string& s, size_t newSize, char fi
if (s.size() > newSize)
return s.substr(0, newSize);
else
- return s + string(newSize - s.size(), fill);
+ return s + std::string(newSize - s.size(), fill);
}
/******************************************************************************/
@@ -357,7 +358,6 @@ std::vector<std::string> TextTools::split(const std::string& s, size_t n)
/******************************************************************************/
std::string TextTools::removeSubstrings(const std::string& s, char blockBeginning, char blockEnding)
-throw (Exception)
{
string t = "";
int blockCount = 0;
@@ -389,7 +389,6 @@ throw (Exception)
/******************************************************************************/
std::string TextTools::removeSubstrings(const std::string& s, char blockBeginning, char blockEnding, std::vector<string>& exceptionsBeginning, std::vector<string>& exceptionsEnding)
-throw (Exception)
{
string t = "";
int blockCount = 0;
@@ -484,15 +483,6 @@ unsigned int TextTools::count(const std::string& s, const std::string& pattern)
/******************************************************************************/
-bool TextTools::startsWith(const std::string& s, const std::string& pattern)
-{
- if (s.size() < pattern.size())
- return false;
- return s.substr(0, pattern.size()) == pattern;
-}
-
-/******************************************************************************/
-
bool TextTools::endsWith(const std::string& s, const std::string& pattern)
{
if (s.size() < pattern.size())
diff --git a/src/Bpp/Text/TextTools.h b/src/Bpp/Text/TextTools.h
index 9ce50d8..ac4a295 100644
--- a/src/Bpp/Text/TextTools.h
+++ b/src/Bpp/Text/TextTools.h
@@ -5,44 +5,41 @@
//
/*
- Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
-
- This software is a computer program whose purpose is to provide basal and
- utilitary classes. This file belongs to the Bio++ Project.
-
- This software is governed by the CeCILL license under French law and
- abiding by the rules of distribution of free software. You can use,
- modify and/ or redistribute the software under the terms of the CeCILL
- license as circulated by CEA, CNRS and INRIA at the following URL
- "http://www.cecill.info".
-
- As a counterpart to the access to the source code and rights to copy,
- modify and redistribute granted by the license, users are provided only
- with a limited warranty and the software's author, the holder of the
- economic rights, and the successive licensors have only limited
- liability.
-
- In this respect, the user's attention is drawn to the risks associated
- with loading, using, modifying and/or developing or reproducing the
- software by the user in light of its specific status of free software,
- that may mean that it is complicated to manipulate, and that also
- therefore means that it is reserved for developers and experienced
- professionals having in-depth computer knowledge. Users are therefore
- encouraged to load and test the software's suitability as regards their
- requirements in conditions enabling the security of their systems and/or
- data to be ensured and, more generally, to use and operate it in the
- same conditions as regards security.
-
- The fact that you are presently reading this means that you have had
- knowledge of the CeCILL license and that you accept its terms.
- */
+ Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+ This software is a computer program whose purpose is to provide basal and
+ utilitary classes. This file belongs to the Bio++ Project.
+
+ This software is governed by the CeCILL license under French law and
+ abiding by the rules of distribution of free software. You can use,
+ modify and/ or redistribute the software under the terms of the CeCILL
+ license as circulated by CEA, CNRS and INRIA at the following URL
+ "http://www.cecill.info".
+
+ As a counterpart to the access to the source code and rights to copy,
+ modify and redistribute granted by the license, users are provided only
+ with a limited warranty and the software's author, the holder of the
+ economic rights, and the successive licensors have only limited
+ liability.
+
+ In this respect, the user's attention is drawn to the risks associated
+ with loading, using, modifying and/or developing or reproducing the
+ software by the user in light of its specific status of free software,
+ that may mean that it is complicated to manipulate, and that also
+ therefore means that it is reserved for developers and experienced
+ professionals having in-depth computer knowledge. Users are therefore
+ encouraged to load and test the software's suitability as regards their
+ requirements in conditions enabling the security of their systems and/or
+ data to be ensured and, more generally, to use and operate it in the
+ same conditions as regards security.
+
+ The fact that you are presently reading this means that you have had
+ knowledge of the CeCILL license and that you accept its terms.
+*/
#ifndef _TEXTTOOLS_H_
#define _TEXTTOOLS_H_
-#include "../Exceptions.h"
-
-
// From the STL:
#include <string>
#include <vector>
@@ -57,354 +54,359 @@ namespace bpp
*/
class TextTools
{
- public:
-
- /**
- * @brief Tell if a string is empty.
- *
- * A string is considered to be 'empty' if it is only made of white
- * spaces.
- *
- * @param s The string to check.
- * @return True if the string has only white characters.
- */
- static bool isEmpty(const std::string& s);
-
- /**
- * @brief Make the string uppercase.
- *
- * @param s The string to analyse.
- * @return A copy of the string with all chars uppercase.
- */
- static std::string toUpper(const std::string& s);
-
- /**
- * @brief Make the string lowercase.
- *
- * @param s The string to analyse.
- * @return A copy of the string with all chars lowercase.
- */
- static std::string toLower(const std::string& s);
-
- /**
- * @brief Tell if a character is a white space or not.
- *
- * @param c The character to check.
- * @return True if c is one of the following: ' ', '\\t', '\\n', '\\r' or '\\f'.
- */
- static bool isWhiteSpaceCharacter(char c);
-
- /**
- * @brief Remove all white spaces characters in a string.
- *
- * @param s The string to parse.
- * @return A copy of 's' without white spaces characters.
- */
- static std::string removeWhiteSpaces (const std::string& s);
-
- /**
- * @brief Remove all white spaces characters at the beginning of a string.
- *
- * @param s The string to parse.
- * @return A copy of 's' beginning with the first non-white character.
- */
- static std::string removeFirstWhiteSpaces (const std::string& s);
-
- /**
- * @brief Remove all white spaces characters at the end of a string.
- *
- * @param s The string to parse.
- * @return A copy of 's' ending with the last non-white character.
- */
- static std::string removeLastWhiteSpaces (const std::string& s);
-
- /**
- * @brief Remove all white spaces characters at the beginning and the end of a string.
- *
- * @param s The string to parse.
- * @return A copy of 's' beginning with the first non-white character
- * and ending with the last one.
- */
- static std::string removeSurroundingWhiteSpaces(const std::string& s);
-
- /**
- * @brief Tell if a character is a new line character or not.
- *
- * @param c The character to check.
- * @return True if c is one of the following: '\\n' or '\\r'.
- */
- static bool isNewLineCharacter(char c);
-
- /**
- * @brief Remove all new line characters in a string.
- *
- * @param s The string to parse.
- * @return A copy of 's' without new line characters.
- */
- static std::string removeNewLines (const std::string& s);
-
- /**
- * @brief Remove all new line characters at the end of a string.
- *
- * @param s The string to parse.
- * @return A copy of 's' ending with the last non-new line character.
- */
- static std::string removeLastNewLines(const std::string& s);
-
- /**
- * @brief Tell is a given character describes a decimal number.
- *
- * @param c The character to check.
- * @return true if the given character is the reprensentation of a decimal number.
- */
- static bool isDecimalNumber(char c);
-
- /**
- * @brief Tell is a given character string describes a decimal number.
- *
- * NB: for now, this parser will not recognize thousands delimiters, and not the scientific notation neither.
- * @param s The string to parse.
- * @param dec The decimal separator.
- * @param scientificNotation character to use for scientific notation (typically 'e' or 'E').
- * @return true if the given string is the representation of a decimal number.
- */
- static bool isDecimalNumber(const std::string& s, char dec = '.', char scientificNotation = 'e');
-
- /**
- * @brief Tell is a given character string describes a decimal integer.
- *
- * NB: for now, this parser will not recognize thousands delimiters, and not the scientific notation neither.
- * @param s The string to parse.
- * @param scientificNotation character to use for scientific notation (typically 'e' or 'E').
- * @return true if the given string is the representation of a decimal integer.
- */
- static bool isDecimalInteger(const std::string& s, char scientificNotation = 'e');
-
- /**
- * @brief General template method to convert to a string.
- *
- * @param t The object to convert.
- * @return A string equal to t.
- */
- template<class T> static std::string toString(T t)
- {
- std::ostringstream oss;
- oss << t;
- return oss.str();
- }
-
- /**
- * @brief Template string conversion.
- *
- * @param t The object to convert.
- * @param precision To use (for numbers).
- * @return A string equal to t.
- */
- template<class T>
- static std::string toString(T t, int precision)
- {
- std::ostringstream oss;
- oss << std::setprecision(precision) << t;
- return oss.str();
- }
-
- /**
- * @brief General template method to convert from string.
- *
- * @param s The string to convert.
- * @return An object from string t.
- */
- template<class T> static T fromString(const std::string& s)
- {
- std::istringstream iss(s);
- T obj;
- iss >> obj;
- return obj;
- }
-
- /**
- * @brief Convert from int to string.
- *
- * @param i The integer to convert.
- * @return A string equal to i.
- */
- static std::string toString(int i);
-
- /**
- * @brief Convert from char to string.
- *
- * @param c The character to convert.
- * @return A string equal to c.
- */
- static std::string toString(char c);
-
- /**
- * @brief Convert from double to string.
- *
- * @param d The double to convert.
- * @param precision To use (for numbers).
- * @return A string equal to d.
- */
- static std::string toString(double d, int precision = 6);
-
- /**
- * @brief Convert from string to int.
- *
- * @param s The string to parse.
- * @param scientificNotation character to use for scientific notation (typically 'e' or 'E').
- * @return The integer corresponding to s.
- * @throw Exception if the string does not specify a valid number.
- */
- static int toInt(const std::string& s, char scientificNotation = 'e') throw (Exception);
-
- /**
- * @brief Convert from string to double.
- *
- * @param s The string to parse.
- * @param dec The decimal separator.
- * @param scientificNotation character to use for scientific notation (typically 'e' or 'E').
- * @return The double corresponding to s.
- * @throw Exception if the string does not specify a valid number.
- */
- static double toDouble(const std::string& s, char dec = '.', char scientificNotation = 'e') throw (Exception);
-
- /**
- * @brief Template to string conversion.
- *
- * @param s The string to parse.
- * @return An object of class R corresponding to s.
- */
- template<class T>
- static T to(const std::string& s)
- {
- std::istringstream iss(s);
- T t;
- iss >> t;
- return t;
- }
-
- /**
- * @brief Send a string of size 'newSize', which is a copy of 's' truncated or
- * filled with character 'fill' at the end.
- *
- * @param s The string to parse.
- * @param newSize The new string size.
- * @param fill The character to use to fill the string id length < newSize.
- * @return A string of size newsize which is a copy from the left of s.
- */
- static std::string resizeRight(const std::string& s, size_t newSize, char fill = ' ');
-
- /**
- * @brief Send a string of size 'newSize', which is a copy of 's' truncated or
- * filled with character 'fill' at the beginning.
- *
- * @param s The string to parse.
- * @param newSize The new string size.
- * @param fill The character to use to fill the string id length < newSize.
- * @return A string of size newsize which is a copy from the right of s.
- */
- static std::string resizeLeft(const std::string& s, size_t newSize, char fill = ' ');
-
- /**
- * @brief Split a string into parts of size 'n'.
- *
- * The last part may contain < n chars.
- *
- * @param s The string to parse.
- * @param n The number of tokens.
- * @return A vector of strings with all tokens.
- */
- static std::vector<std::string> split(const std::string& s, size_t n);
-
- /**
- * @brief Remove substrings from a string.
- *
- * All substrings beginning with blockBeginning
- * and ending with blockEnding will be removed.
- * Nesting blocks are allowed, the most extern block will be removed.
- *
- * @param s The string to parse.
- * @param blockBeginning The character specifying the beginning of each block.
- * @param blockEnding The character specifying the end of each block.
- * @return The string with all blocks removed.
- * @throw Exception If some blocks are not well formed.
- */
- static std::string removeSubstrings(const std::string& s, char blockBeginning, char blockEnding)
- throw (Exception);
+ public:
+
+ /**
+ * @brief Tell if a string is empty.
+ *
+ * A string is considered to be 'empty' if it is only made of white
+ * spaces.
+ *
+ * @param s The string to check.
+ * @return True if the string has only white characters.
+ */
+ static bool isEmpty(const std::string& s);
+
+ /**
+ * @brief Make the string uppercase.
+ *
+ * @param s The string to analyse.
+ * @return A copy of the string with all chars uppercase.
+ */
+ static std::string toUpper(const std::string& s);
+
+ /**
+ * @brief Make the string lowercase.
+ *
+ * @param s The string to analyse.
+ * @return A copy of the string with all chars lowercase.
+ */
+ static std::string toLower(const std::string& s);
+
+ /**
+ * @brief Tell if a character is a white space or not.
+ *
+ * @param c The character to check.
+ * @return True if c is one of the following: ' ', '\\t', '\\n', '\\r' or '\\f'.
+ */
+ static bool isWhiteSpaceCharacter(char c);
+
+ /**
+ * @brief Remove all white spaces characters in a string.
+ *
+ * @param s The string to parse.
+ * @return A copy of 's' without white spaces characters.
+ */
+ static std::string removeWhiteSpaces (const std::string& s);
+
+ /**
+ * @brief Remove all white spaces characters at the beginning of a string.
+ *
+ * @param s The string to parse.
+ * @return A copy of 's' beginning with the first non-white character.
+ */
+ static std::string removeFirstWhiteSpaces (const std::string& s);
+
+ /**
+ * @brief Remove all white spaces characters at the end of a string.
+ *
+ * @param s The string to parse.
+ * @return A copy of 's' ending with the last non-white character.
+ */
+ static std::string removeLastWhiteSpaces (const std::string& s);
+
+ /**
+ * @brief Remove all white spaces characters at the beginning and the end of a string.
+ *
+ * @param s The string to parse.
+ * @return A copy of 's' beginning with the first non-white character
+ * and ending with the last one.
+ */
+ static std::string removeSurroundingWhiteSpaces(const std::string& s);
+
+ /**
+ * @brief Tell if a character is a new line character or not.
+ *
+ * @param c The character to check.
+ * @return True if c is one of the following: '\\n' or '\\r'.
+ */
+ static bool isNewLineCharacter(char c);
+
+ /**
+ * @brief Remove all new line characters in a string.
+ *
+ * @param s The string to parse.
+ * @return A copy of 's' without new line characters.
+ */
+ static std::string removeNewLines (const std::string& s);
+
+ /**
+ * @brief Remove all new line characters at the end of a string.
+ *
+ * @param s The string to parse.
+ * @return A copy of 's' ending with the last non-new line character.
+ */
+ static std::string removeLastNewLines(const std::string& s);
+
+ /**
+ * @brief Tell is a given character describes a decimal number.
+ *
+ * @param c The character to check.
+ * @return true if the given character is the reprensentation of a decimal number.
+ */
+ static bool isDecimalNumber(char c);
+
+ /**
+ * @brief Tell is a given character string describes a decimal number.
+ *
+ * NB: for now, this parser will not recognize thousands delimiters, and not the scientific notation neither.
+ * @param s The string to parse.
+ * @param dec The decimal separator.
+ * @param scientificNotation character to use for scientific notation (typically 'e' or 'E').
+ * @return true if the given string is the representation of a decimal number.
+ */
+ static bool isDecimalNumber(const std::string& s, char dec = '.', char scientificNotation = 'e');
+
+ /**
+ * @brief Tell is a given character string describes a decimal integer.
+ *
+ * NB: for now, this parser will not recognize thousands delimiters, and not the scientific notation neither.
+ * @param s The string to parse.
+ * @param scientificNotation character to use for scientific notation (typically 'e' or 'E').
+ * @return true if the given string is the representation of a decimal integer.
+ */
+ static bool isDecimalInteger(const std::string& s, char scientificNotation = 'e');
+
+ /**
+ * @brief General template method to convert to a string.
+ *
+ * @param t The object to convert.
+ * @return A string equal to t.
+ */
+ template<class T> static std::string toString(T t)
+ {
+ std::ostringstream oss;
+ oss << t;
+ return oss.str();
+ }
+
+ /**
+ * @brief Template string conversion.
+ *
+ * @param t The object to convert.
+ * @param precision To use (for numbers).
+ * @return A string equal to t.
+ */
+ template<class T>
+ static std::string toString(T t, int precision)
+ {
+ std::ostringstream oss;
+ oss << std::setprecision(precision) << t;
+ return oss.str();
+ }
+
+ /**
+ * @brief General template method to convert from string.
+ *
+ * @param s The string to convert.
+ * @return An object from string t.
+ */
+ template<class T> static T fromString(const std::string& s)
+ {
+ std::istringstream iss(s);
+ T obj;
+ iss >> obj;
+ return obj;
+ }
+
+ /**
+ * @brief Convert from int to string.
+ *
+ * @param i The integer to convert.
+ * @return A string equal to i.
+ */
+ static std::string toString(int i);
+
+ /**
+ * @brief Convert from char to string.
+ *
+ * @param c The character to convert.
+ * @return A string equal to c.
+ */
+ static std::string toString(char c);
+
+ /**
+ * @brief Convert from double to string.
+ *
+ * @param d The double to convert.
+ * @param precision To use (for numbers).
+ * @return A string equal to d.
+ */
+ static std::string toString(double d, int precision = 6);
+
+ /**
+ * @brief Convert from string to int.
+ *
+ * @param s The string to parse.
+ * @param scientificNotation character to use for scientific notation (typically 'e' or 'E').
+ * @return The integer corresponding to s.
+ * @throw Exception if the string does not specify a valid number.
+ */
+ static int toInt(const std::string& s, char scientificNotation = 'e');
+
+ /**
+ * @brief Convert from string to double.
+ *
+ * @param s The string to parse.
+ * @param dec The decimal separator.
+ * @param scientificNotation character to use for scientific notation (typically 'e' or 'E').
+ * @return The double corresponding to s.
+ * @throw Exception if the string does not specify a valid number.
+ */
+ static double toDouble(const std::string& s, char dec = '.', char scientificNotation = 'e');
+
+ /**
+ * @brief Template to string conversion.
+ *
+ * @param s The string to parse.
+ * @return An object of class R corresponding to s.
+ */
+ template<class T>
+ static T to(const std::string& s)
+ {
+ std::istringstream iss(s);
+ T t;
+ iss >> t;
+ return t;
+ }
+
+ /**
+ * @brief Send a string of size 'newSize', which is a copy of 's' truncated or
+ * filled with character 'fill' at the end.
+ *
+ * @param s The string to parse.
+ * @param newSize The new string size.
+ * @param fill The character to use to fill the string id length < newSize.
+ * @return A string of size newsize which is a copy from the left of s.
+ */
+
+ static std::string resizeRight(const std::string& s, size_t newSize, char fill = ' ');
+
+ /**
+ * @brief Send a string of size 'newSize', which is a copy of 's' truncated or
+ * filled with character 'fill' at the beginning.
+ *
+ * @param s The string to parse.
+ * @param newSize The new string size.
+ * @param fill The character to use to fill the string id length < newSize.
+ * @return A string of size newsize which is a copy from the right of s.
+ */
+ static std::string resizeLeft(const std::string& s, size_t newSize, char fill = ' ');
+
+ /**
+ * @brief Split a string into parts of size 'n'.
+ *
+ * The last part may contain < n chars.
+ *
+ * @param s The string to parse.
+ * @param n The number of tokens.
+ * @return A vector of strings with all tokens.
+ */
+ static std::vector<std::string> split(const std::string& s, size_t n);
+
+ /**
+ * @brief Remove substrings from a string.
+ *
+ * All substrings beginning with blockBeginning
+ * and ending with blockEnding will be removed.
+ * Nesting blocks are allowed, the most extern block will be removed.
+ *
+ * @param s The string to parse.
+ * @param blockBeginning The character specifying the beginning of each block.
+ * @param blockEnding The character specifying the end of each block.
+ * @return The string with all blocks removed.
+ * @throw Exception If some blocks are not well formed.
+ */
+ static std::string removeSubstrings(const std::string& s, char blockBeginning, char blockEnding);
- /**
- * @brief Remove substrings from a string, unless they match some specific substrings.
- *
- * All substrings beginning with blockBeginning
- * and ending with blockEnding will be removed, except if they begin with
- * a string included in the vector exceptionsBeginning or end with a string
- * included in the vector exceptionsEnding.
- * Nesting blocks are allowed, the most extern block will be removed.
- *
- * @param s The string to parse.
- * @param blockBeginning The character specifying the beginning of each block.
- * @param blockEnding The character specifying the end of each block.
- * @param exceptionsBeginning A vector containing all strings specifying the beginning of blocks that should not be removed.
- * @param exceptionsEnding A vector containing all strings specifying the ending of blocks that should not be removed.
- * @return The string with all blocks removed.
- * @throw Exception If some blocks are not well formed.
- */
- static std::string removeSubstrings(const std::string& s, char blockBeginning, char blockEnding, std::vector<std::string>& exceptionsBeginning, std::vector<std::string>& exceptionsEnding)
- throw (Exception);
+ /**
+ * @brief Remove substrings from a string, unless they match some specific substrings.
+ *
+ * All substrings beginning with blockBeginning
+ * and ending with blockEnding will be removed, except if they begin with
+ * a string included in the vector exceptionsBeginning or end with a string
+ * included in the vector exceptionsEnding.
+ * Nesting blocks are allowed, the most extern block will be removed.
+ *
+ * @param s The string to parse.
+ * @param blockBeginning The character specifying the beginning of each block.
+ * @param blockEnding The character specifying the end of each block.
+ * @param exceptionsBeginning A vector containing all strings specifying the beginning of blocks that should not be removed.
+ * @param exceptionsEnding A vector containing all strings specifying the ending of blocks that should not be removed.
+ * @return The string with all blocks removed.
+ * @throw Exception If some blocks are not well formed.
+ */
+ static std::string removeSubstrings(const std::string& s, char blockBeginning, char blockEnding, std::vector<std::string>& exceptionsBeginning, std::vector<std::string>& exceptionsEnding);
- /**
- * @brief Remove all occurences of a character in a string.
- *
- * @param s The string to parse.
- * @param c The character to remove.
- * @return The string with all specified chars removed.
- */
- static std::string removeChar(const std::string& s, char c);
-
- /**
- * @brief Count the occurences of a given pattern in a string.
- *
- * @param s The string to search.
- * @param pattern The pattern to use (this is a mere string, not a regexp!).
- * @return The number of occurences of 'pattern' in 's'.
- */
- static unsigned int count(const std::string& s, const std::string& pattern);
-
- /**
- * @brief Tell is a string begins with a certain motif.
- *
- * @param s The string to search.
- * @param pattern The pattern to use (this is a mere string, not a regexp!).
- * @return true/false
- */
- static bool startsWith(const std::string& s, const std::string& pattern);
-
- /**
- * @brief Tell is a string ends with a certain motif.
- *
- * @param s The string to search.
- * @param pattern The pattern to use (this is a mere string, not a regexp!).
- * @return true/false
- */
- static bool endsWith(const std::string& s, const std::string& pattern);
-
- /**
- * @brief Tell is a string contains a certain motif.
- *
- * @param s The string to search.
- * @param pattern The pattern to use (this is a mere string, not a regexp!).
- * @return true/false
- */
- static bool hasSubstring(const std::string& s, const std::string& pattern);
-
- /**
- * @brief Replacement of all non-overlapping occurrences of a certain motif in a string.
- *
- * @param target String to be modified
- * @param query The motif to look for
- * @param replacement The replacement string
- */
- static void replaceAll(std::string& target, const std::string& query, const std::string& replacement);
+ /**
+ * @brief Remove all occurences of a character in a string.
+ *
+ * @param s The string to parse.
+ * @param c The character to remove.
+ * @return The string with all specified chars removed.
+ */
+ static std::string removeChar(const std::string& s, char c);
+
+ /**
+ * @brief Count the occurences of a given pattern in a string.
+ *
+ * @param s The string to search.
+ * @param pattern The pattern to use (this is a mere string, not a regexp!).
+ * @return The number of occurences of 'pattern' in 's'.
+ */
+ static unsigned int count(const std::string& s, const std::string& pattern);
+
+ /**
+ * @brief Tell is a string begins with a certain motif.
+ *
+ * @param s The string to search.
+ * @param pattern The pattern to use (this is a mere string, not a regexp!).
+ * @return true/false
+ */
+
+ static bool startsWith(const std::string& s, const std::string& pattern)
+ {
+ if (s.size() < pattern.size())
+ return false;
+ return s.substr(0, pattern.size()) == pattern;
+ }
+
+ /**
+ * @brief Tell is a string ends with a certain motif.
+ *
+ * @param s The string to search.
+ * @param pattern The pattern to use (this is a mere string, not a regexp!).
+ * @return true/false
+ */
+ static bool endsWith(const std::string& s, const std::string& pattern);
+
+ /**
+ * @brief Tell is a string contains a certain motif.
+ *
+ * @param s The string to search.
+ * @param pattern The pattern to use (this is a mere string, not a regexp!).
+ * @return true/false
+ */
+ static bool hasSubstring(const std::string& s, const std::string& pattern);
+
+ /**
+ * @brief Replacement of all non-overlapping occurrences of a certain motif in a string.
+ *
+ * @param target String to be modified
+ * @param query The motif to look for
+ * @param replacement The replacement string
+ */
+ static void replaceAll(std::string& target, const std::string& query, const std::string& replacement);
};
diff --git a/src/Bpp/Graph/BasicONode.cpp b/src/Bpp/Version.h
similarity index 86%
rename from src/Bpp/Graph/BasicONode.cpp
rename to src/Bpp/Version.h
index 1ab3f09..a1f5415 100644
--- a/src/Bpp/Graph/BasicONode.cpp
+++ b/src/Bpp/Version.h
@@ -1,11 +1,11 @@
-//
-// File: BasicONode.cpp
-// Author: Sylvain Gaillard
-// Created: 14/01/2011 14:59:07
-//
+//
+// File: Version.h
+// Created by: Julien Dutheil
+// Created on: Sun Apr 2 20:00 2017
+//
/*
-Copyright or © or Copr. Bio++ Development Team, (January 12, 2011)
+Copyright or © or Copr. Bio++ Development Team, (April 2, 2017)
This software is a computer program whose purpose is to provide utilitary
classes. This file belongs to the Bio++ Project.
@@ -37,9 +37,10 @@ The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms.
*/
-#include "BasicONode.h"
+#ifndef _VERSION_H_
+#define _VERSION_H_
-using namespace bpp;
+#define BPP_VERSION 2.3.0
-BasicONode::BasicONode() {}
+#endif //_VERSION_H_
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7ae06c6..33aa38c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,52 +1,40 @@
# CMake script for Bio++ Core
-# Author: Sylvain Gaillard and Julien Dutheil
+# Authors:
+# Sylvain Gaillard
+# Julien Dutheil
+# Francois Gindraud (2017)
# Created: 17/08/2009
# File list
-SET(CPP_FILES
- Bpp/Exceptions.cpp
- Bpp/BppString.cpp
+set (CPP_FILES
Bpp/App/ApplicationTools.cpp
Bpp/App/BppApplication.cpp
Bpp/App/NumCalcApplicationTools.cpp
- Bpp/Io/FileTools.cpp
- Bpp/Io/BppOParametrizableFormat.cpp
- Bpp/Io/BppODiscreteDistributionFormat.cpp
- Bpp/Io/IoDiscreteDistributionFactory.cpp
- Bpp/Utils/AttributesTools.cpp
- Bpp/Text/KeyvalTools.cpp
- Bpp/Text/NestedStringTokenizer.cpp
- Bpp/Text/StringTokenizer.cpp
- Bpp/Text/TextTools.cpp
- Bpp/Graph/BasicONode.cpp
- Bpp/Graph/BasicTNode.cpp
+ Bpp/BppString.cpp
+ Bpp/Exceptions.cpp
+ Bpp/Graph/GlobalGraph.cpp
Bpp/Graphics/ColorTools.cpp
- Bpp/Graphics/GraphicDevice.cpp
Bpp/Graphics/Fig/XFigGraphicDevice.cpp
Bpp/Graphics/Fig/XFigLaTeXFontManager.cpp
Bpp/Graphics/Fig/XFigPostscriptFontManager.cpp
Bpp/Graphics/Font/Font.cpp
+ Bpp/Graphics/GraphicDevice.cpp
Bpp/Graphics/Latex/DvipsColorSet.cpp
Bpp/Graphics/Latex/PgfGraphicDevice.cpp
Bpp/Graphics/Molscript/MolscriptColorSet.cpp
- Bpp/Graphics/Svg/SvgGraphicDevice.cpp
Bpp/Graphics/R/RColorSet.cpp
- Bpp/Numeric/NumTools.cpp
- Bpp/Numeric/Parameter.cpp
- Bpp/Numeric/ParameterExceptions.cpp
- Bpp/Numeric/ParameterList.cpp
- Bpp/Numeric/Random/RandomTools.cpp
- Bpp/Numeric/Random/ContingencyTableGenerator.cpp
- Bpp/Numeric/Random/Uniform01K.cpp
- Bpp/Numeric/Random/Uniform01QD.cpp
- Bpp/Numeric/Random/Uniform01WH.cpp
+ Bpp/Graphics/Svg/SvgGraphicDevice.cpp
+ Bpp/Io/BppODiscreteDistributionFormat.cpp
+ Bpp/Io/BppOParametrizableFormat.cpp
+ Bpp/Io/FileTools.cpp
+ Bpp/Io/IoDiscreteDistributionFactory.cpp
Bpp/Numeric/AbstractParameterAliasable.cpp
Bpp/Numeric/AbstractParametrizable.cpp
Bpp/Numeric/AdaptiveKernelDensityEstimation.cpp
- Bpp/Numeric/VectorTools.cpp
Bpp/Numeric/AutoParameter.cpp
Bpp/Numeric/DataTable.cpp
Bpp/Numeric/Function/AbstractOptimizer.cpp
+ Bpp/Numeric/Function/BfgsMultiDimensions.cpp
Bpp/Numeric/Function/BrentOneDimension.cpp
Bpp/Numeric/Function/ConjugateGradientMultiDimensions.cpp
Bpp/Numeric/Function/DirectionFunction.cpp
@@ -55,10 +43,10 @@ SET(CPP_FILES
Bpp/Numeric/Function/FunctionTools.cpp
Bpp/Numeric/Function/GoldenSectionSearch.cpp
Bpp/Numeric/Function/MetaOptimizer.cpp
- Bpp/Numeric/Function/NewtonOneDimension.cpp
Bpp/Numeric/Function/NewtonBacktrackOneDimension.cpp
- Bpp/Numeric/Function/BfgsMultiDimensions.cpp
+ Bpp/Numeric/Function/NewtonOneDimension.cpp
Bpp/Numeric/Function/OneDimensionOptimizationTools.cpp
+ Bpp/Numeric/Function/Operators/ComputationTree.cpp
Bpp/Numeric/Function/OptimizationStopCondition.cpp
Bpp/Numeric/Function/PowellMultiDimensions.cpp
Bpp/Numeric/Function/ReparametrizationFunctionWrapper.cpp
@@ -66,14 +54,17 @@ SET(CPP_FILES
Bpp/Numeric/Function/SimpleNewtonMultiDimensions.cpp
Bpp/Numeric/Function/ThreePointsNumericalDerivative.cpp
Bpp/Numeric/Function/TwoPointsNumericalDerivative.cpp
- Bpp/Numeric/Hmm/HmmLikelihood.cpp
Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.cpp
- Bpp/Numeric/Hmm/FullHmmTransitionMatrix.cpp
Bpp/Numeric/Hmm/AutoCorrelationTransitionMatrix.cpp
+ Bpp/Numeric/Hmm/FullHmmTransitionMatrix.cpp
+ Bpp/Numeric/Hmm/HmmLikelihood.cpp
Bpp/Numeric/Hmm/LogsumHmmLikelihood.cpp
Bpp/Numeric/Hmm/LowMemoryRescaledHmmLikelihood.cpp
Bpp/Numeric/Hmm/RescaledHmmLikelihood.cpp
- Bpp/Numeric/Prob/Simplex.cpp
+ Bpp/Numeric/NumTools.cpp
+ Bpp/Numeric/Parameter.cpp
+ Bpp/Numeric/ParameterExceptions.cpp
+ Bpp/Numeric/ParameterList.cpp
Bpp/Numeric/Prob/AbstractDiscreteDistribution.cpp
Bpp/Numeric/Prob/BetaDiscreteDistribution.cpp
Bpp/Numeric/Prob/ConstantDistribution.cpp
@@ -84,173 +75,61 @@ SET(CPP_FILES
Bpp/Numeric/Prob/InvariantMixedDiscreteDistribution.cpp
Bpp/Numeric/Prob/MixtureOfDiscreteDistributions.cpp
Bpp/Numeric/Prob/SimpleDiscreteDistribution.cpp
+ Bpp/Numeric/Prob/Simplex.cpp
Bpp/Numeric/Prob/TruncatedExponentialDiscreteDistribution.cpp
Bpp/Numeric/Prob/UniformDiscreteDistribution.cpp
+ Bpp/Numeric/Random/ContingencyTableGenerator.cpp
+ Bpp/Numeric/Random/RandomTools.cpp
+ Bpp/Numeric/Random/Uniform01K.cpp
+ Bpp/Numeric/Random/Uniform01QD.cpp
+ Bpp/Numeric/Random/Uniform01WH.cpp
Bpp/Numeric/Stat/ContingencyTableTest.cpp
- Bpp/Numeric/Stat/StatTools.cpp
+ Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.cpp
Bpp/Numeric/Stat/Mva/DualityDiagram.cpp
Bpp/Numeric/Stat/Mva/PrincipalComponentAnalysis.cpp
- Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.cpp
+ Bpp/Numeric/Stat/StatTools.cpp
+ Bpp/Numeric/VectorTools.cpp
+ Bpp/Text/KeyvalTools.cpp
+ Bpp/Text/NestedStringTokenizer.cpp
+ Bpp/Text/StringTokenizer.cpp
+ Bpp/Text/TextTools.cpp
+ Bpp/Utils/AttributesTools.cpp
)
-SET(H_FILES
- Bpp/BppString.h
- Bpp/BppBoolean.h
- Bpp/BppVector.h
- Bpp/Clonable.h
- Bpp/Exceptions.h
- Bpp/App/ApplicationTools.h
- Bpp/App/BppApplication.h
- Bpp/App/NumCalcApplicationTools.h
- Bpp/Graph/UNode.h
- Bpp/Graph/ONode.h
- Bpp/Graph/TNode.h
- Bpp/Graph/BasicONode.h
- Bpp/Graph/BasicTNode.h
- Bpp/Graphics/AbstractGraphicDevice.h
- Bpp/Graphics/ColorManager.h
- Bpp/Graphics/ColorSet.h
- Bpp/Graphics/ColorTools.h
- Bpp/Graphics/DefaultColorSet.h
- Bpp/Graphics/GraphicDevice.h
- Bpp/Graphics/Point2D.h
- Bpp/Graphics/Point2DTools.h
- Bpp/Graphics/RgbColor.h
- Bpp/Io/FileTools.h
- Bpp/Io/IoFormat.h
- Bpp/Io/IoParametrizable.h
- Bpp/Io/IoDiscreteDistribution.h
- Bpp/Io/IoDiscreteDistributionFactory.h
- Bpp/Io/OutputStream.h
- Bpp/Io/BppOParametrizableFormat.h
- Bpp/Io/BppODiscreteDistributionFormat.h
- Bpp/Numeric/AbstractParameterAliasable.h
- Bpp/Numeric/AbstractParametrizable.h
- Bpp/Numeric/AdaptiveKernelDensityEstimation.h
- Bpp/Numeric/AutoParameter.h
- Bpp/Numeric/Constraints.h
- Bpp/Numeric/DataTableExceptions.h
- Bpp/Numeric/DataTable.h
- Bpp/Numeric/Number.h
- Bpp/Numeric/NumConstants.h
- Bpp/Numeric/NumTools.h
- Bpp/Numeric/ParameterAliasable.h
- Bpp/Numeric/ParameterExceptions.h
- Bpp/Numeric/Parameter.h
- Bpp/Numeric/ParameterList.h
- Bpp/Numeric/Parametrizable.h
- Bpp/Numeric/ParametrizableCollection.cpp
- Bpp/Numeric/TransformedParameter.h
- Bpp/Numeric/Random/RandomFactory.h
- Bpp/Numeric/Random/RandomTools.h
- Bpp/Numeric/Random/ContingencyTableGenerator.h
- Bpp/Numeric/Random/Uniform01K.h
- Bpp/Numeric/Random/Uniform01QD.h
- Bpp/Numeric/Random/Uniform01WH.h
- Bpp/Numeric/VectorExceptions.h
- Bpp/Numeric/VectorTools.h
- Bpp/Numeric/Range.h
- Bpp/Text/KeyvalTools.h
- Bpp/Text/NestedStringTokenizer.h
- Bpp/Text/StringTokenizer.h
- Bpp/Text/TextTools.h
- Bpp/Utils/AttributesTools.h
- Bpp/Utils/MapTools.h
- Bpp/Graphics/Fig/XFigGraphicDevice.h
- Bpp/Graphics/Fig/XFigLaTeXFontManager.h
- Bpp/Graphics/Fig/XFigPostscriptFontManager.h
- Bpp/Graphics/Font/Font.h
- Bpp/Graphics/Font/FontManager.h
- Bpp/Graphics/Latex/DvipsColorSet.h
- Bpp/Graphics/Latex/PgfGraphicDevice.h
- Bpp/Graphics/Molscript/MolscriptColorSet.h
- Bpp/Graphics/R/RColorSet.h
- Bpp/Graphics/Svg/SvgGraphicDevice.h
- Bpp/Numeric/Function/AbstractNumericalDerivative.h
- Bpp/Numeric/Function/AbstractOptimizer.h
- Bpp/Numeric/Function/BrentOneDimension.h
- Bpp/Numeric/Function/ConjugateGradientMultiDimensions.h
- Bpp/Numeric/Function/DirectionFunction.h
- Bpp/Numeric/Function/DownhillSimplexMethod.h
- Bpp/Numeric/Function/FivePointsNumericalDerivative.h
- Bpp/Numeric/Function/Functions.h
- Bpp/Numeric/Function/FunctionTools.h
- Bpp/Numeric/Function/GoldenSectionSearch.h
- Bpp/Numeric/Function/MetaOptimizer.h
- Bpp/Numeric/Function/NewtonOneDimension.h
- Bpp/Numeric/Function/NewtonBacktrackOneDimension.h
- Bpp/Numeric/Function/BfgsMultiDimensions.h
- Bpp/Numeric/Function/OneDimensionOptimizationTools.h
- Bpp/Numeric/Function/OptimizationStopCondition.h
- Bpp/Numeric/Function/Optimizer.h
- Bpp/Numeric/Function/PowellMultiDimensions.h
- Bpp/Numeric/Function/ReparametrizationFunctionWrapper.h
- Bpp/Numeric/Function/SimpleMultiDimensions.h
- Bpp/Numeric/Function/SimpleNewtonMultiDimensions.h
- Bpp/Numeric/Function/ThreePointsNumericalDerivative.h
- Bpp/Numeric/Function/TwoPointsNumericalDerivative.h
- Bpp/Numeric/Hmm/HmmEmissionProbabilities.h
- Bpp/Numeric/Hmm/HmmExceptions.h
- Bpp/Numeric/Hmm/HmmLikelihood.h
- Bpp/Numeric/Hmm/HmmStateAlphabet.h
- Bpp/Numeric/Hmm/HmmTransitionMatrix.h
- Bpp/Numeric/Hmm/AbstractHmmTransitionMatrix.h
- Bpp/Numeric/Hmm/FullHmmTransitionMatrix.h
- Bpp/Numeric/Hmm/AutoCorrelationTransitionMatrix.h
- Bpp/Numeric/Hmm/LogsumHmmLikelihood.h
- Bpp/Numeric/Hmm/LowMemoryRescaledHmmLikelihood.h
- Bpp/Numeric/Hmm/RescaledHmmLikelihood.h
- Bpp/Numeric/Matrix/EigenValue.h
- Bpp/Numeric/Matrix/LUDecomposition.h
- Bpp/Numeric/Matrix/Matrix.h
- Bpp/Numeric/Matrix/MatrixTools.h
- Bpp/Numeric/Prob/Simplex.h
- Bpp/Numeric/Prob/AbstractDiscreteDistribution.h
- Bpp/Numeric/Prob/BetaDiscreteDistribution.h
- Bpp/Numeric/Prob/ConstantDistribution.h
- Bpp/Numeric/Prob/DirichletDiscreteDistribution.h
- Bpp/Numeric/Prob/DiscreteDistribution.h
- Bpp/Numeric/Prob/ExponentialDiscreteDistribution.h
- Bpp/Numeric/Prob/GammaDiscreteDistribution.h
- Bpp/Numeric/Prob/GaussianDiscreteDistribution.h
- Bpp/Numeric/Prob/InvariantMixedDiscreteDistribution.h
- Bpp/Numeric/Prob/MixtureOfDiscreteDistributions.h
- Bpp/Numeric/Prob/MultipleDiscreteDistribution.h
- Bpp/Numeric/Prob/SimpleDiscreteDistribution.h
- Bpp/Numeric/Prob/TruncatedExponentialDiscreteDistribution.h
- Bpp/Numeric/Prob/UniformDiscreteDistribution.h
- Bpp/Numeric/Stat/StatTest.h
- Bpp/Numeric/Stat/ContingencyTableTest.h
- Bpp/Numeric/Stat/StatTools.h
- Bpp/Numeric/Stat/Mva/DualityDiagram.h
- Bpp/Numeric/Stat/Mva/PrincipalComponentAnalysis.h
- Bpp/Numeric/Stat/Mva/CorrespondenceAnalysis.h
-)
-
# Build the static lib
-ADD_LIBRARY(bppcore-static STATIC ${CPP_FILES})
-SET_TARGET_PROPERTIES(bppcore-static
- PROPERTIES OUTPUT_NAME bpp-core
- CLEAN_DIRECT_OUTPUT 1
+add_library (${PROJECT_NAME}-static STATIC ${CPP_FILES})
+target_include_directories (${PROJECT_NAME}-static PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>
)
-TARGET_LINK_LIBRARIES(bppcore-static ${LIBS})
+set_target_properties (${PROJECT_NAME}-static PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
+target_link_libraries (${PROJECT_NAME}-static ${BPP_LIBS_STATIC})
# Build the shared lib
-ADD_LIBRARY(bppcore-shared SHARED ${CPP_FILES})
-SET_TARGET_PROPERTIES(bppcore-shared
- PROPERTIES OUTPUT_NAME bpp-core
- CLEAN_DIRECT_OUTPUT 1
- VERSION ${BPPCORE_VERSION}
- SOVERSION ${BPPCORE_VERSION_MAJOR}
+add_library (${PROJECT_NAME}-shared SHARED ${CPP_FILES})
+target_include_directories (${PROJECT_NAME}-shared PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>
)
-TARGET_LINK_LIBRARIES(bppcore-shared ${LIBS})
-
-# Install libs
-INSTALL(TARGETS bppcore-static bppcore-shared DESTINATION lib${LIB_SUFFIX})
-
-# Install headers
-INSTALL(DIRECTORY Bpp/ DESTINATION include/Bpp FILES_MATCHING PATTERN "*.h")
-
-# Generate generic include files (.all)
-INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_SOURCE_DIR}/genIncludes.sh ${CMAKE_PREFIX_PATH}/include/Bpp)")
+set_target_properties (${PROJECT_NAME}-shared
+ PROPERTIES OUTPUT_NAME ${PROJECT_NAME}
+ MACOSX_RPATH 1
+ VERSION ${${PROJECT_NAME}_VERSION}
+ SOVERSION ${${PROJECT_NAME}_VERSION_MAJOR}
+ )
+target_link_libraries (${PROJECT_NAME}-shared ${BPP_LIBS_SHARED})
+# Install libs and headers
+install (
+ TARGETS ${PROJECT_NAME}-static ${PROJECT_NAME}-shared
+ EXPORT ${PROJECT_NAME}-targets
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX}
+ )
+install (
+ DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Bpp
+ DESTINATION include
+ FILES_MATCHING PATTERN "*.h"
+ )
+# Install cmake file representing targets
+install (EXPORT ${PROJECT_NAME}-targets DESTINATION ${cmake-package-location})
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 40a3b87..7086962 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,102 +1,24 @@
# CMake script for bpp-core unit tests
-# Author: Julien Dutheil
+# Authors:
+# Julien Dutheil
+# Francois Gindraud (2017)
# Created: 27/10/2010
-MACRO(TEST_FIND_LIBRARY OUTPUT_LIBS lib_name include_to_find)
- #start:
- FIND_PATH(${lib_name}_INCLUDE_DIR ${include_to_find})
-
- SET(${lib_name}_NAMES ${lib_name} ${lib_name}.lib ${lib_name}.dll)
- FIND_LIBRARY(${lib_name}_LIBRARY NAMES ${${lib_name}_NAMES})
- IF(${lib_name}_LIBRARY)
- MESSAGE("-- Library ${lib_name} found here:")
- MESSAGE(" includes: ${${lib_name}_INCLUDE_DIR}")
- MESSAGE(" dynamic libraries: ${${lib_name}_LIBRARY}")
- MESSAGE(WARNING "Library ${lib_name} is already installed in the system tree. Test will be built against it. This may lead to unexpected results. You may want to do 'make install' before 'make test', or remove the installed version.")
- ELSE()
- SET(${lib_name}_LIBRARY "-L../src -lbpp-core")
- SET(${lib_name}_INCLUDE_DIR "../src/")
- ENDIF()
- INCLUDE_DIRECTORIES(${${lib_name}_INCLUDE_DIR})
- SET(${OUTPUT_LIBS} ${${OUTPUT_LIBS}} ${${lib_name}_LIBRARY})
-ENDMACRO(TEST_FIND_LIBRARY)
-
-#Find the bpp-core library library:
-TEST_FIND_LIBRARY(LIBS bpp-core Bpp/Clonable.h)
-
-ADD_EXECUTABLE(test_numconstants test_numconstants.cpp)
-TARGET_LINK_LIBRARIES(test_numconstants ${LIBS})
-ADD_TEST(test_numconstants "test_numconstants")
-
-ADD_EXECUTABLE(test_eigen test_eigen.cpp)
-TARGET_LINK_LIBRARIES(test_eigen ${LIBS})
-ADD_TEST(test_eigen "test_eigen")
-
-ADD_EXECUTABLE(test_matrices test_matrices.cpp)
-TARGET_LINK_LIBRARIES(test_matrices ${LIBS})
-ADD_TEST(test_matrices "test_matrices")
-
-ADD_EXECUTABLE(test_derivative1 test_derivative1.cpp)
-TARGET_LINK_LIBRARIES(test_derivative1 ${LIBS})
-ADD_TEST(test_derivative1 "test_derivative1")
-
-ADD_EXECUTABLE(test_reparametrization test_reparametrization.cpp)
-TARGET_LINK_LIBRARIES(test_reparametrization ${LIBS})
-ADD_TEST(test_reparametrization "test_reparametrization")
-
-ADD_EXECUTABLE(test_downhill test_downhill.cpp)
-TARGET_LINK_LIBRARIES(test_downhill ${LIBS})
-ADD_TEST(test_downhill "test_downhill")
-
-ADD_EXECUTABLE(test_powell test_powell.cpp)
-TARGET_LINK_LIBRARIES(test_powell ${LIBS})
-ADD_TEST(test_powell "test_powell")
-
-ADD_EXECUTABLE(test_gradient test_gradient.cpp)
-TARGET_LINK_LIBRARIES(test_gradient ${LIBS})
-ADD_TEST(test_gradient "test_gradient")
-
-ADD_EXECUTABLE(test_bfgs test_bfgs.cpp)
-TARGET_LINK_LIBRARIES(test_bfgs ${LIBS})
-ADD_TEST(test_bfgs "test_bfgs")
-
-ADD_EXECUTABLE(test_distributions test_distributions.cpp)
-TARGET_LINK_LIBRARIES(test_distributions ${LIBS})
-ADD_TEST(test_distributions "test_distributions")
-
-ADD_EXECUTABLE(test_simplex test_simplex.cpp)
-TARGET_LINK_LIBRARIES(test_simplex ${LIBS})
-ADD_TEST(test_simplex "test_simplex")
-
-ADD_EXECUTABLE(test_stats test_stats.cpp)
-TARGET_LINK_LIBRARIES(test_stats ${LIBS})
-ADD_TEST(test_stats "test_stats")
-
-ADD_EXECUTABLE(test_mva test_mva.cpp)
-TARGET_LINK_LIBRARIES(test_mva ${LIBS})
-ADD_TEST(test_mva "test_mva")
-
-ADD_EXECUTABLE(test_sample test_sample.cpp)
-TARGET_LINK_LIBRARIES(test_sample ${LIBS})
-ADD_TEST(test_sample "test_sample")
-
-ADD_EXECUTABLE(test_range test_range.cpp)
-TARGET_LINK_LIBRARIES(test_range ${LIBS})
-ADD_TEST(test_range "test_range")
-
-ADD_EXECUTABLE(test_text_tools test_text_tools.cpp)
-TARGET_LINK_LIBRARIES(test_text_tools ${LIBS})
-ADD_TEST(test_text_tools "test_text_tools")
-
-IF(UNIX)
- SET_PROPERTY(TEST test_numconstants test_eigen test_matrices test_derivative1 test_reparametrization test_downhill test_powell test_gradient test_bfgs test_distributions test_stats test_mva test_sample test_range test_text_tools test_simplex PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:../src")
-ENDIF()
-
-IF(APPLE)
- SET_PROPERTY(TEST test_numconstants test_eigen test_matrices test_derivative1 test_reparametrization test_downhill test_powell test_gradient test_bfgs test_distributions test_stats test_mva test_sample test_range test_text_tools test_simplex PROPERTY ENVIRONMENT "DYLD_LIBRARY_PATH=$ENV{DYLD_LIBRARY_PATH}:../src")
-ENDIF()
-
-IF(WIN32)
- SET(ENV{PATH} "$ENV{PATH};..\\src")
-ENDIF()
-
+# Add all tests.
+# Any .cpp file in test/ is considered to be a test.
+# It will be compiled as a standalone program (must contain a main()).
+# A test is considered to succeed if it returns EXIT_SUCCESS (usually 0).
+# Tests are linked to the the shared library target.
+
+file (GLOB test_cpp_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
+foreach (test_cpp_file ${test_cpp_files})
+ # Add each test (named as the filename without extension)
+ get_filename_component (test_name ${test_cpp_file} NAME_WE)
+ add_executable (${test_name} ${test_cpp_file})
+ target_link_libraries (${test_name} ${PROJECT_NAME}-shared)
+ add_test (
+ NAME ${test_name}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMAND ${test_name}
+ )
+endforeach (test_cpp_file)
diff --git a/test/test_dAGraphObs.cpp b/test/test_dAGraphObs.cpp
new file mode 100644
index 0000000..34d2aed
--- /dev/null
+++ b/test/test_dAGraphObs.cpp
@@ -0,0 +1,159 @@
+//
+// File: test_dAGraphObs.cpp
+// Created by: Laurent Guéguen
+// Created on: 2016
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+This software is a computer program whose purpose is to provide classes
+for numerical calculus. This file is part of the Bio++ project.
+
+This software is governed by the CeCILL license under French law and
+abiding by the rules of distribution of free software. You can use,
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info".
+
+As a counterpart to the access to the source code and rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty and the software's author, the holder of the
+economic rights, and the successive licensors have only limited
+liability.
+
+In this respect, the user's attention is drawn to the risks associated
+with loading, using, modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean that it is complicated to manipulate, and that also
+therefore means that it is reserved for developers and experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or
+data to be ensured and, more generally, to use and operate it in the
+same conditions as regards security.
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#include "../src/Bpp/Graph/DAGraph.h"
+#include "../src/Bpp/Graph/AssociationDAGraphImplObserver.h"
+
+#include <vector>
+#include <iostream>
+using namespace bpp;
+using namespace std;
+
+int main() {
+ AssociationDAGlobalGraphObserver<string,unsigned int> grObs;
+
+ shared_ptr<string> zero(new string("zero"));
+ shared_ptr<string> one(new string("one"));
+ shared_ptr<string> two(new string("two"));
+ shared_ptr<string> three(new string("three"));
+ shared_ptr<string> four(new string("four"));
+ shared_ptr<string> five(new string("five"));
+ shared_ptr<string> six(new string("six"));
+ shared_ptr<unsigned int> r3(new unsigned int(3));
+ shared_ptr<unsigned int> r1(new unsigned int(5));
+
+ cout << "Creating node zero." << endl;
+ grObs.createNode(zero);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Creating node one from the number zero." << endl;
+ grObs.createNode(one);
+ grObs.addFather(one,zero,r1);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << "Creating node two from the number one." << endl;
+ grObs.createNode(one,two);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Linking two to zero." << endl;
+ grObs.addFather(zero,two,r3);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+
+ cout << "Linking one to three and two to four." << endl;
+ grObs.createNode(one,three);
+ grObs.createNode(two,four);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << endl;
+
+ cout << "Linking three to zero." << endl;
+ grObs.addFather(zero,three);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ // so now we have zero -> one -> two -> zero ...
+ vector<shared_ptr<string> > fromOne = grObs.getOutgoingNeighbors(zero);
+ vector<shared_ptr<string> > fromThree = grObs.getOutgoingNeighbors(two);
+ bool test = (*(fromOne.begin()) == one) && (*(fromThree.begin()) == zero);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << "Is this a DAG?\n " << (grObs.isValid()? "TRUE":"FALSE") << endl;
+
+ // the DAG must be considered as unvalid at this point
+ test &= !grObs.isValid();
+
+
+ cout << "Removing 2->0 and 3->0"<< endl;
+ grObs.removeSon(two,zero);
+ grObs.removeSon(three,zero);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << "Is this a DAG?\n " << (grObs.isValid()? "TRUE":"FALSE") << endl;
+ // the DAG is valid at this point
+ test &= grObs.isValid();
+
+ cout << endl;
+ cout << "Iteration on sons of 1:" << endl;
+
+ unique_ptr<AssociationDAGraphObserver<string, unsigned int>::NodeIterator> in0It=grObs.sonsIterator(one);
+
+ for (;!in0It->end();in0It->next())
+ cout << ***in0It << endl;
+
+ cout << "Reroot on one" << endl;
+
+ grObs.rootAt(one);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << "Linking 3->2"<< endl;
+ grObs.addFather(three, two);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << endl;
+
+ cout << "Is this a DAG?\n " << (grObs.isValid()? "TRUE":"FALSE") << endl;
+ // the DAG must be considered as valid at this point
+ test &= grObs.isValid();
+ cout << endl;
+
+ cout << "Add nodes five and six" << endl;
+ grObs.createNode(five);
+ grObs.createNode(six);
+ grObs.addFather(four,five);
+ grObs.addFather(five,six);
+ grObs.addFather(six,four);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << endl;
+
+ cout << "Is this a DAG?\n " << (grObs.isValid()? "TRUE":"FALSE") << endl;
+ // the tree must be considered as unvalid at this point
+ test &= !grObs.isValid();
+ cout << endl;
+
+ cout << "Reroot on two" << endl;
+
+ grObs.rootAt(two);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << "Is this a DAG?\n " << (grObs.isValid()? "TRUE":"FALSE") << endl;
+ // the tree must be considered as unvalid at this point
+ test &= grObs.isValid();
+ cout << endl;
+
+ cout << "Test " << (test? "passed":"failed") << endl;
+
+ return (test ? 0 : 1);
+}
diff --git a/test/test_graphObs.cpp b/test/test_graphObs.cpp
new file mode 100644
index 0000000..769c4bc
--- /dev/null
+++ b/test/test_graphObs.cpp
@@ -0,0 +1,144 @@
+//
+// File: test_graphObs.cpp
+// Created by: Thomas Bigot
+// Created on: 2016
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+This software is a computer program whose purpose is to provide classes
+for numerical calculus. This file is part of the Bio++ project.
+
+This software is governed by the CeCILL license under French law and
+abiding by the rules of distribution of free software. You can use,
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info".
+
+As a counterpart to the access to the source code and rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty and the software's author, the holder of the
+economic rights, and the successive licensors have only limited
+liability.
+
+In this respect, the user's attention is drawn to the risks associated
+with loading, using, modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean that it is complicated to manipulate, and that also
+therefore means that it is reserved for developers and experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or
+data to be ensured and, more generally, to use and operate it in the
+same conditions as regards security.
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#include "../src/Bpp/Graph/AssociationGraphImplObserver.h"
+#include <vector>
+#include <iostream>
+using namespace bpp;
+using namespace std;
+
+int main() {
+ AssociationGlobalGraphObserver<string,unsigned int> grObs(true);
+ shared_ptr<string> zero(new string("zero"));
+ shared_ptr<string> one(new string("one"));
+ shared_ptr<string> two(new string("two"));
+ shared_ptr<string> three(new string("three"));
+ shared_ptr<unsigned int> r3(new unsigned int(3));
+ shared_ptr<unsigned int> r2(new unsigned int(4));
+
+ cout << "Creating node zero." << endl;
+ grObs.createNode(zero);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Creating node one from the number zero." << endl;
+ grObs.createNode(zero,one);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Creating node two from the number one." << endl;
+ grObs.createNode(one,two);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Linking two to zero." << endl;
+ grObs.link(two,zero,r3);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Linking one to three." << endl;
+ grObs.createNode(one,three,r2);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Linking three to zero." << endl;
+ grObs.link(three,zero);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ // so now we have zero -> one -> two -> zero ...
+ vector<shared_ptr<string> > fromZero = grObs.getOutgoingNeighbors(zero);
+ vector<shared_ptr<string> > fromTwo = grObs.getOutgoingNeighbors(two);
+
+ bool test = (*(fromZero.begin()) == one) && (*(fromTwo.begin()) == zero);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+
+ cout << endl;
+ cout << "Iteration on all nodes:" << endl;
+
+ unique_ptr<AssociationGlobalGraphObserver<string, unsigned int>::NodeIterator> nIt=grObs.allNodesIterator();
+
+ for (;!nIt->end();nIt->next())
+ {
+ cout << ***nIt << endl;
+ }
+
+ cout << endl;
+ cout << "Iteration on all edges:" << endl;
+
+ unique_ptr<AssociationGlobalGraphObserver<string, unsigned int>::EdgeIterator> eIt=grObs.allEdgesIterator();
+
+ for (;!eIt->end();eIt->next())
+ {
+ cout << ***eIt << endl;
+ }
+
+ cout << endl;
+ cout << "Iteration on outgoing nodes neighbor of 1:" << endl;
+
+ unique_ptr<AssociationGlobalGraphObserver<string, unsigned int>::NodeIterator> on1It=grObs.outgoingNeighborNodesIterator(one);
+
+ for (;!on1It->end();on1It->next())
+ {
+ cout << ***on1It << endl;
+ }
+
+ cout << endl;
+ cout << "Iteration on incoming nodes neighbor of 0:" << endl;
+
+ unique_ptr<AssociationGlobalGraphObserver<string, unsigned int>::NodeIterator> in0It=grObs.incomingNeighborNodesIterator(zero);
+
+ for (;!in0It->end();in0It->next())
+ {
+ cout << ***in0It << endl;
+ }
+
+ cout << endl;
+ cout << "Iteration on outgoing edges neighbor of 1:" << endl;
+
+ unique_ptr<AssociationGlobalGraphObserver<string, unsigned int>::EdgeIterator> oe1It=grObs.outgoingEdgesIterator(one);
+
+ for (;!oe1It->end();oe1It->next())
+ {
+ cout << ***oe1It << endl;
+ }
+
+ cout << endl;
+
+ cout << "Iteration on incoming edges neighbor of 0:" << endl;
+
+ unique_ptr<AssociationGlobalGraphObserver<string, unsigned int>::EdgeIterator> ie0It=grObs.incomingEdgesIterator(zero);
+
+ for (;!ie0It->end();ie0It->next())
+ {
+ cout << ***ie0It << endl;
+ }
+
+
+ return (test ? 0 : 1);
+}
diff --git a/test/test_treeGraphObs.cpp b/test/test_treeGraphObs.cpp
new file mode 100644
index 0000000..04238a3
--- /dev/null
+++ b/test/test_treeGraphObs.cpp
@@ -0,0 +1,178 @@
+//
+// File: test_treeGraphObs.cpp
+// Created by: Thomas Bigot
+// Created on: 2016
+//
+
+/*
+Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
+
+This software is a computer program whose purpose is to provide classes
+for numerical calculus. This file is part of the Bio++ project.
+
+This software is governed by the CeCILL license under French law and
+abiding by the rules of distribution of free software. You can use,
+modify and/ or redistribute the software under the terms of the CeCILL
+license as circulated by CEA, CNRS and INRIA at the following URL
+"http://www.cecill.info".
+
+As a counterpart to the access to the source code and rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty and the software's author, the holder of the
+economic rights, and the successive licensors have only limited
+liability.
+
+In this respect, the user's attention is drawn to the risks associated
+with loading, using, modifying and/or developing or reproducing the
+software by the user in light of its specific status of free software,
+that may mean that it is complicated to manipulate, and that also
+therefore means that it is reserved for developers and experienced
+professionals having in-depth computer knowledge. Users are therefore
+encouraged to load and test the software's suitability as regards their
+requirements in conditions enabling the security of their systems and/or
+data to be ensured and, more generally, to use and operate it in the
+same conditions as regards security.
+
+The fact that you are presently reading this means that you have had
+knowledge of the CeCILL license and that you accept its terms.
+*/
+
+#include "../src/Bpp/Graph/TreeGraph.h"
+#include "../src/Bpp/Graph/AssociationTreeGraphImplObserver.h"
+
+
+#include <vector>
+#include <iostream>
+using namespace bpp;
+using namespace std;
+
+int main() {
+ AssociationTreeGlobalGraphObserver<string,unsigned int> grObs(true);
+
+ shared_ptr<string> zero(new string("zero"));
+ shared_ptr<string> one(new string("one"));
+ shared_ptr<string> two(new string("two"));
+ shared_ptr<string> three(new string("three"));
+ shared_ptr<string> four(new string("four"));
+ shared_ptr<string> five(new string("five"));
+ shared_ptr<unsigned int> r3(new unsigned int(3));
+ shared_ptr<unsigned int> r1(new unsigned int(5));
+ shared_ptr<unsigned int> r2(new unsigned int(10));
+
+ cout << "Creating node zero." << endl;
+ grObs.createNode(zero);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Creating node one from the number zero." << endl;
+ grObs.createNode(one);
+ grObs.link(zero,one,r2);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "The father branch of zero is " << *(grObs.getEdgeToFather(one)) << endl;
+ cout << "The father node of one is " << *(grObs.getFather(one)) << endl;
+
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+
+ cout << "Creating node two from the number one." << endl;
+ grObs.createNode(one,two);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Linking two to zero." << endl;
+ grObs.link(two,zero,r3);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Linking one to three and two to four." << endl;
+ grObs.createNode(one,three);
+ grObs.createNode(two,four,r1);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << "Linking three to zero." << endl;
+ grObs.link(three,zero);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ vector<shared_ptr<string> > fromOne = grObs.getOutgoingNeighbors(zero);
+ vector<shared_ptr<string> > fromThree = grObs.getOutgoingNeighbors(two);
+ bool test = (*(fromOne.begin()) == one) && (*(fromThree.begin()) == zero);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+
+ cout << "Is this a tree?\n " << (grObs.isValid()? "TRUE":"FALSE") << endl;
+
+ // the tree must be considered as unvalid at this point
+ test &= !grObs.isValid();
+
+ cout << "Removing 2->0 and 3->0"<< endl;
+ grObs.unlink(two,zero);
+ grObs.unlink(three,zero);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << "Is this a tree?\n " << (grObs.isValid()? "TRUE":"FALSE") << endl;
+ // the tree is valid at this point
+ test &= grObs.isValid();
+
+ cout << endl;
+ cout << "Iteration on sons of 1:" << endl;
+
+ unique_ptr<AssociationTreeGraphObserver<string, unsigned int>::NodeIterator> in0It=grObs.sonsIterator(one);
+
+ for (;!in0It->end();in0It->next())
+ {
+ cout << ***in0It << endl;
+ }
+
+ cout << endl;
+ cout << " Outgoing edges of 2:" << endl;
+
+ vector<shared_ptr<unsigned int> > ve=grObs.getBranches(two);
+ for (size_t i=0; i<ve.size();i++)
+ cout << *ve[i] << endl;
+
+ cout << endl;
+
+ cout << "Iteration on outgoing edges of 2:" << endl;
+ unique_ptr<AssociationTreeGraphObserver<string, unsigned int>::EdgeIterator> oe1It=grObs.branchesIterator(two);
+
+ for (;!oe1It->end();oe1It->next())
+ {
+ cout << ***oe1It << endl;
+ }
+
+ cout << endl ;
+
+ // add another root
+
+ cout << "Add another root " << endl;
+
+ grObs.createNode(five);
+ grObs.link(five,two);
+
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << "Is this a tree?\n " << (grObs.isValid()? "TRUE":"FALSE") << endl;
+ // the tree is not valid at this point
+ test &= !grObs.isValid();
+
+ cout << "Reroot on one" << endl;
+
+ try {
+ grObs.rootAt(one);
+ }
+ catch(Exception& e)
+ {
+ cout << "First undirect the tree." << endl;
+ grObs.getGraph()->makeUndirected();
+ grObs.getGraph()->outputToDot(std::cout,"undirected");
+ cout << "Then root." << endl;
+ grObs.rootAt(one);
+ }
+
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+
+ cout << "Linking 3->2"<< endl;
+ grObs.link(three, two);
+ grObs.getGraph()->outputToDot(std::cout,"myTestDirGrObs");
+ cout << "Is this a tree?\n " << (grObs.isValid()? "TRUE":"FALSE") << endl;
+ // the tree must be considered as unvalid at this point
+ test &= !grObs.isValid();
+
+ cout << "Test " << (test? "passed":"failed") << endl;
+
+ return (test ? 0 : 1);
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/libbpp-core.git
More information about the debian-med-commit
mailing list