From 07fa07d72cc38c5d02d546f4bddcd2eed53c5d6c Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 5 May 2014 17:04:44 +0200 Subject: [PATCH 01/98] first cmaes addition --- Makefile | 10 +- cmake/modules/RootBuildOptions.cmake | 2 + config/Makefile.depend | 4 + config/Makefile.in | 5 + configure | 645 +++++++++--------- core/base/src/TPluginManager.cxx | 4 +- .../P010_Minuit2Minimizer.C | 4 +- graf2d/asimage/src/libAfterImage/asfont.c | 6 +- math/CMakeLists.txt | 1 + math/mathcore/src/Factory.cxx | 18 +- tutorials/fit/minuit2GausFit.C | 2 +- 11 files changed, 367 insertions(+), 334 deletions(-) diff --git a/Makefile b/Makefile index a0149f1551509..69b07750e3462 100644 --- a/Makefile +++ b/Makefile @@ -82,7 +82,7 @@ MODULES = build interpreter/llvm interpreter/cling core/metautils \ io/io math/mathcore net/net core/zip core/lzma math/matrix \ core/newdelete hist/hist tree/tree graf2d/freetype \ graf2d/mathtext graf2d/graf graf2d/gpad graf3d/g3d \ - gui/gui math/minuit hist/histpainter tree/treeplayer \ + gui/gui math/minuit math/cmaes hist/histpainter tree/treeplayer \ gui/ged tree/treeviewer math/physics graf2d/postscript \ core/rint html montecarlo/eg \ geom/geom geom/geompainter montecarlo/vmc \ @@ -244,6 +244,12 @@ endif ifeq ($(BUILDMINUIT2),yes) MODULES += math/minuit2 endif +ifeq ($(BUILDCMAES),yes) +MODULES += math/cmaes +endif +ifeq ($(BUILDCMAES),yes) +MODULES += math/cmaes +endif ifeq ($(BUILDUNURAN),yes) MODULES += math/unuran endif @@ -320,7 +326,7 @@ MODULES += core/unix core/winnt graf2d/x11 graf2d/x11ttf \ sql/oracle io/xmlparser math/mathmore \ tmva math/genetic io/hdfs graf2d/fitsio roofit/roofitcore \ roofit/roofit roofit/roostats roofit/histfactory \ - math/minuit2 net/monalisa math/fftw sql/odbc math/unuran \ + math/minuit2 math/cmaes net/monalisa math/fftw sql/odbc math/unuran \ geom/geocad geom/gdml graf3d/eve net/glite misc/memstat \ math/genvector net/bonjour graf3d/gviz3d graf2d/gviz \ proof/proofbench proof/afdsmgrd graf2d/ios \ diff --git a/cmake/modules/RootBuildOptions.cmake b/cmake/modules/RootBuildOptions.cmake index 943ab1e60916a..a5f7f37894e7b 100644 --- a/cmake/modules/RootBuildOptions.cmake +++ b/cmake/modules/RootBuildOptions.cmake @@ -109,6 +109,7 @@ ROOT_BUILD_OPTION(castor ON "CASTOR support, requires libshift from CASTOR >= 1. ROOT_BUILD_OPTION(chirp ON "Chirp support (Condor remote I/O), requires libchirp_client") ROOT_BUILD_OPTION(clarens ON "Clarens RPC support, optionally used by PROOF") ROOT_BUILD_OPTION(cling ON "Enable new CLING C++ interpreter") +ROOT_BUILD_OPTION(cmaes ON "Build the libcmaes minimizer library wrapper") ROOT_BUILD_OPTION(cocoa ${cocoa_defvalue} "Use native Cocoa/Quartz graphics backend (MacOS X only)") ROOT_BUILD_OPTION(davix ${davix_defvalue} "DavIx library for HTTP/WEBDAV access") ROOT_BUILD_OPTION(dcache ON "dCache support, requires libdcap from DESY") @@ -132,6 +133,7 @@ ROOT_BUILD_OPTION(ldap ON "LDAP support, requires (Open)LDAP libs") ROOT_BUILD_OPTION(mathmore ON "Build the new libMathMore extended math library, requires GSL (vers. >= 1.8)") ROOT_BUILD_OPTION(memstat ${memstat_defvalue} "A memory statistics utility, helps to detect memory leaks") ROOT_BUILD_OPTION(minuit2 OFF "Build the new libMinuit2 minimizer library") +ROOT_BUILD_OPTION(cmaes ON "Build the libcmaes minimizer library wrapper") ROOT_BUILD_OPTION(monalisa ON "Monalisa monitoring support, requires libapmoncpp") ROOT_BUILD_OPTION(mysql ON "MySQL support, requires libmysqlclient") ROOT_BUILD_OPTION(odbc ON "ODBC support, requires libiodbc or libodbc") diff --git a/config/Makefile.depend b/config/Makefile.depend index 0009b8a4cf7fa..f130a27cf1161 100644 --- a/config/Makefile.depend +++ b/config/Makefile.depend @@ -26,6 +26,7 @@ HTMLLIBDEPM = $(GRAFLIB) $(THREADLIB) MATHMORELIBDEPM = $(MATHCORELIB) MINUITLIBDEPM = $(GRAFLIB) $(HISTLIB) $(MATRIXLIB) $(MATHCORELIB) MINUIT2LIBDEPM = $(GRAFLIB) $(HISTLIB) $(MATRIXLIB) $(MATHCORELIB) +CMAESLIBDEPM = $(GRAFLIB) $(HISTLIB) $(MATHCORELIB) FUMILILIBDEPM = $(GRAFLIB) $(HISTLIB) $(MATHCORELIB) TREELIBDEPM = $(NETLIB) $(IOLIB) $(THREADLIB) TREEPLAYERLIBDEPM = $(TREELIB) $(G3DLIB) $(GRAFLIB) $(HISTLIB) $(GPADLIB) \ @@ -162,6 +163,7 @@ SPECTRUMPAINTERLIBDEP = $(SPECTRUMPAINTERLIBDEPM) HTMLLIBDEP = $(HTMLLIBDEPM) MINUITLIBDEP = $(MINUITLIBDEPM) MINUIT2LIBDEP = $(MINUIT2LIBDEPM) +CMAESLIBDEP = $(CMAESLIBDEPM) MATHMORELIBDEP = $(MATHMORELIBDEPM) FUMILILIBDEP = $(FUMILILIBDEPM) TREELIBDEP = $(TREELIBDEPM) @@ -271,6 +273,7 @@ MINUITLIBEXTRA = lib/libGraf.lib lib/libHist.lib lib/libMatrix.lib \ lib/libMathCore.lib MINUIT2LIBEXTRA = lib/libGraf.lib lib/libHist.lib lib/libMatrix.lib \ lib/libMathCore.lib +CMAESLIBEXTRA = lib/libGraf.lib lib/libHist.lib lib/libMathCore.lib MATHMORELIBEXTRA = lib/libMathCore.lib FUMILILIBEXTRA = lib/libGraf.lib lib/libHist.lib lib/libMathCore.lib TREELIBEXTRA = lib/libNet.lib lib/libRIO.lib lib/libThread.lib @@ -433,6 +436,7 @@ SPECTRUMPAINTERLIBEXTRA = -Llib -lGraf -lHist HTMLLIBEXTRA = -Llib -lGraf -lThread MINUITLIBEXTRA = -Llib -lGraf -lHist -lMatrix -lMathCore MINUIT2LIBEXTRA = -Llib -lGraf -lHist -lMatrix -lMathCore +CMAESLIBEXTRA = -Llib -lGraf -lHist -lMathCore FUMILILIBEXTRA = -Llib -lGraf -lHist -lMathCore MATHMORELIBEXTRA = -Llib -lMathCore TREELIBEXTRA = -Llib -lNet -lRIO -lThread diff --git a/config/Makefile.in b/config/Makefile.in index 2283fc545ad5f..93ab667f5ec0f 100644 --- a/config/Makefile.in +++ b/config/Makefile.in @@ -390,6 +390,11 @@ BUILDROOFIT := @buildroofit@ BUILDMINUIT2 := @buildminuit2@ +BUILDCMAES := @buildcmaes@ +CMAESINCDIR := $(filter-out -I/usr/include, @cmaesincdir@) +CMAESLIBDIR := @cmaeslibdir@ +CMAESLIB := -lcmaes + BUILDUNURAN := @buildunuran@ BUILDVC := @buildvc@ diff --git a/configure b/configure index 10e658be64ba0..d01bc73063acb 100755 --- a/configure +++ b/configure @@ -1,4 +1,4 @@ -#!/bin/bash +#! /bin/sh # # A (not so) simple configure script. # @@ -27,17 +27,12 @@ altcc= altcxx= altf77= altld= -altccset= -gcctoolchain= host= deprecated_options=" \ enable_mathcore \ enable_cern \ enable_editline \ - enable_cintex \ - enable_reflex \ - enable_cxx11 \ " options=" \ @@ -55,10 +50,13 @@ options=" \ enable_builtin_pcre \ enable_builtin_zlib \ enable_builtin_lzma \ - enable_builtin_llvm \ + enable_cxx11 \ enable_libcxx \ enable_castor \ enable_chirp \ + enable_cintex \ + enable_cling \ + enable_cmaes \ enable_cocoa \ enable_davix \ enable_dcache \ @@ -69,7 +67,6 @@ options=" \ enable_gviz \ enable_gdml \ enable_genvector \ - enable_geocad \ enable_gfal \ enable_glite \ enable_globus \ @@ -91,6 +88,7 @@ options=" \ enable_python \ enable_qt \ enable_qtgsi \ + enable_reflex \ enable_roofit \ enable_ruby \ enable_rfio \ @@ -107,7 +105,6 @@ options=" \ enable_unuran \ enable_vc \ enable_vdt \ - enable_werror \ enable_winrtdebug \ enable_x11 \ enable_xft \ @@ -146,13 +143,14 @@ for c in $options $deprecated_options; do done for c in $options ; do eval ${c}_explicit="" ; done -enable_cxx11=yes +enable_cxx11=no enable_libcxx=no +enable_cling=no enable_cocoa= enable_afs=no enable_alloc=no +enable_cmaes=yes enable_gdml=no -enable_geocad=no enable_globus=no enable_explicitlink=no enable_gsl_shared=no @@ -168,7 +166,6 @@ enable_table=no enable_thread=yes # cannot be disabled (not in above options list) enable_unuran=no enable_vc=no -enable_werror=no enable_winrtdebug= enable_builtin_freetype=no enable_builtin_ftgl=no @@ -176,17 +173,16 @@ enable_builtin_glew=no enable_builtin_pcre=no enable_builtin_zlib=no enable_builtin_lzma=no -enable_builtin_llvm=yes enable_afdsmgrd=no if test "x$ENABLEALL" = "xyes"; then + enable_cmaes=yes enable_gdml=yes - enable_geocad=yes enable_qt=yes enable_qtgsi=yes enable_roofit=yes enable_minuit2=yes - #enable_ruby=yes #not supported in ROOT v6.0.0 yet + enable_ruby=yes enable_table=yes enable_unuran=yes enable_vc=yes @@ -202,9 +198,6 @@ rm -f $logfile envvars=" THREAD \ ZLIB \ -LIBTIFF \ -LIBJPEG \ -LIBPNG \ LZMA \ OPENGL \ MYSQL \ @@ -240,9 +233,10 @@ SSL \ AFS \ ROOFIT \ MINUIT2 \ +CMAES \ TABLE \ XMLDIR \ -CASROOT \ +ROOTDICTTYPE \ VC \ DAVIX \ " @@ -396,14 +390,14 @@ check_libcompat() { case $arch in macosx) - logmsg " lipo $chklibcompat -verify_arch i386" - if lipo $chklibcompat -verify_arch i386 ; then + logmsg " lipo -info $chklibcompat | grep ' i386'" + if lipo -info $chklibcompat | grep ' i386' > /dev/null 2>& 1 ; then ret=1 fi ;; macosx64) - logmsg " lipo $chklibcompat -verify_arch x86_64" - if lipo $chklibcompat -verify_arch x86_64 ; then + logmsg " lipo -info $chklibcompat | grep ' x86_64'" + if lipo -info $chklibcompat | grep ' x86_64' > /dev/null 2>& 1 ; then ret=1 fi ;; @@ -427,7 +421,7 @@ check_libcxxcompat() { # The result of the check is stored in is_libcxxcompat, 1 if true, # 0 otherwise, which should be immediately copied, since the variable # will be overwritten at next invocation of this function. - # To skip this check, in case std types are not used in the public + # To avoid this check, in case std types are not used in the public # API of the library, set skipchecklibcxxcompat="yes". is_libcxxcompat=1 @@ -1299,6 +1293,7 @@ check_explicit() fi } +#_____________________________________________________________________ invoke_preprocessor() { # This function will try to preprocess a given file. The result is stored in # preprocessor_output, which should be immediately copied, since the @@ -1341,6 +1336,7 @@ guess_architecture() { logmsg "rele=$rele" case "$arch:$chip:$rele" in aix*) arch=aix5 ;; + osf1*:alpha:*) arch=alphacxx6 ;; freebsd*:*:[789]*) arch=freebsd7 ;; freebsd*:*:6*) arch=freebsd5 ;; freebsd*:*:5*) arch=freebsd5 ;; @@ -1351,9 +1347,10 @@ guess_architecture() { hurd*:*:*) arch=hurddeb ;; linux:ia64:*) arch=linuxia64gcc ;; linux:x86_64:*) arch=linuxx8664gcc ;; - linux:x32:*) arch=linuxx32gcc ;; + linux:alpha:*) arch=linuxalphagcc ;; linux:arm*:*) arch=linuxarm ;; linux:hppa*:*) arch=linux ;; + linux:mips:*) arch=linuxmips ;; linux:sparc*:*) arch=linux ;; linux:parisc*:*) arch=linuxhppa ;; linux:ppc64*:*) arch=linuxppc64gcc ;; @@ -1364,6 +1361,7 @@ guess_architecture() { lynx:*:*) arch=lynxos ;; darwin:power*:*) arch=macosx ;; darwin:*86*:*) arch=macosx ;; + irix*:sgi*:*) arch=sgicc ;; sunos:sun*:6*) arch=solarisCC5 ;; sunos:sun*:5*) arch=solarisCC5 ;; sunos:sun*:4*) arch=solaris ;; @@ -1547,6 +1545,14 @@ THISROOTCSHIN=${ac_srcdir}/config/thisroot.csh THISROOTCSHOUT=bin/thisroot.csh THISROOTBATIN=${ac_srcdir}/config/thisroot.bat THISROOTBATOUT=bin/thisroot.bat +GENREFLEXSHIN=${ac_srcdir}/config/genreflex.in +GENREFLEXSHOUT=bin/genreflex +GENREFLEXBATIN=${ac_srcdir}/config/genreflex.bat.in +GENREFLEXBATOUT=bin/genreflex.bat +GENREFLEXROOTCINTSHIN=${ac_srcdir}/config/genreflex-rootcint.in +GENREFLEXROOTCINTSHOUT=bin/genreflex-rootcint +GENREFLEXROOTCINTBATIN=${ac_srcdir}/config/genreflex-rootcint.bat.in +GENREFLEXROOTCINTBATOUT=bin/genreflex-rootcint.bat SETXRDSHIN=${ac_srcdir}/config/setxrd.sh SETXRDSHOUT=bin/setxrd.sh SETXRDCSHIN=${ac_srcdir}/config/setxrd.csh @@ -1576,6 +1582,7 @@ FIRST argument one of the architecures given at the end of this message. --bindir Binary installation dir (/bin) --build Build configuration [debug, ...], overrides the ROOTBUILD shell variable + --cintincdir CINT interpeted headers (/cint) --datadir Data installation dir (/share/root) --docdir Documentation (/share/doc/root) --elispdir Where to put Emacs Lisp (/share/emacs/site-lisp) @@ -1592,22 +1599,11 @@ FIRST argument one of the architecures given at the end of this message. --testdir Tests (/test) --tutdir Tutorials (/tutorial) -If any of the flags --datadir, --docdir, --etcdir, --iconpath +If any of the flags --cintincdir, --datadir, --docdir, --etcdir, --iconpath --incdir, --libdir, --macrodir, --mandir, or --prefix is given, ROOT will be compiled with static directory names, and you should not set the ROOTSYS environment variable. -To reduce the output of configure by removing the trailing howto message, use: - - --nohowto - -Use the flag: - - --fail-on-missing - -to force configure to fail if a component that has been explicitly enabled -is missing some dependencies and can not be built. - enable/disable options, prefix with either --enable- or --disable- afdsmgrd Dataset manager for PROOF-based analysis facilities @@ -1616,16 +1612,20 @@ enable/disable options, prefix with either --enable- or --disable- asimage Image processing support, requires libAfterImage astiff Include tiff support in image processing bonjour Bonjour support, requires libdns_sd and/or Avahi - builtin-afterimage Build included libAfterImage, or use system libAfterImage - builtin-ftgl Build included libFTGL, or use system libftgl - builtin-freetype Build included libfreetype, or use system libfreetype - builtin-glew Build included libGLEW, or use system libGLEW - builtin-pcre Build included libpcre, or use system libpcre - builtin-zlib Build included libz, or use system libz - builtin-lzma Build included liblzma, or use system liblzma - libcxx Build using libc++, required by clang option (MacOS X only, for the time being) + builtin-afterimage Built included libAfterImage, or use system libAfterImage + builtin-ftgl Built included libFTGL, or use system libftgl + builtin-freetype Built included libfreetype, or use system libfreetype + builtin-glew Built included libGLEW, or use system libGLEW + builtin-pcre Built included libpcre, or use system libpcre + builtin-zlib Built included libz, or use system libz + builtin-lzma Built included liblzma, or use system liblzma + cxx11 Build using C++11 compatible mode, requires gcc > 4.7.x or clang + libcxx Build using libc++, required by clang cxx11 option (MacOS X only, for the time being) castor CASTOR support, requires libshift from CASTOR >= 1.5.2 chirp Chirp filesystem support, requires cctools >= 3.2.2 + cintex Build the libCintex Reflex interface library + cling Use cling as interpreter backend (experimental!), needs --with-llvm-config + cmaes Build the wrapper to the libcmaes mininmizer library cocoa Use native Cocoa/Quartz graphics backend (MacOS X only) davix DavIx library for HTTP/WEBDAV access dcache dCache support, requires libdcap from DESY @@ -1635,7 +1635,6 @@ enable/disable options, prefix with either --enable- or --disable- fitsio Read images and data from FITS files, requires cfitsio gviz Graphs visualization support, requires graphviz gdml GDML writer and reader - geocad ROOT-CAD Interface gfal GFAL support, requires libgfal globus Globus authentication support, requires Globus toolkit glite gLite support, requires libglite-api-wrapper v.3 from GSI (https://subversion.gsi.de/trac/dgrid/wiki) @@ -1644,7 +1643,7 @@ enable/disable options, prefix with either --enable- or --disable- krb5 Kerberos5 support, requires Kerberos libs ldap LDAP support, requires (Open)LDAP libs genvector Build the new libGenVector library - mathmore Build the new libMathMore extended math library, requires GSL (vers. >= 1.10) + mathmore Build the new libMathMore extended math library, requires GSL (vers. >= 1.8) memstat A memory statistics utility, helps to detect memory leaks minuit2 Build the new libMinuit2 minimizer library monalisa Monalisa monitoring support, requires libapmoncpp @@ -1655,9 +1654,10 @@ enable/disable options, prefix with either --enable- or --disable- pgsql PostgreSQL support, requires libpq pythia6 Pythia6 EG support, requires libPythia6 pythia8 Pythia8 EG support, requires libPythia8 >= 8180 - python Python ROOT bindings, requires python >= 2.5 - qt Qt graphics backend, requires libqt >= 4.8 - qtgsi GSI's Qt integration, requires libqt >= 4.8 + python Python ROOT bindings, requires python >= 2.2 + qt Qt graphics backend, requires libqt >= 4.x + qtgsi GSI's Qt integration, requires libqt >= 3 + reflex Build the libReflex dictionary library rfio RFIO support, requires libshift from CASTOR >= 1.5.2 roofit Build the libRooFit advanced fitting package rpath Set run-time library load path on executables @@ -1671,9 +1671,8 @@ enable/disable options, prefix with either --enable- or --disable- ssl SSL encryption support, requires openssl table Build libTable contrib library tmva Build TMVA multi variate analysis library - unuran UNURAN - package for generating non-uniform random numbers vc Vc adds a few new types for portable and intuitive SIMD programming - werror Turn on -Werror on most systems to force warnings to be errors + unuran UNURAN - package for generating non-uniform random numbers winrtdebug Link against the Windows debug runtime library x11 X11 support xml XML parser interface @@ -1710,6 +1709,7 @@ with options, prefix with --with-, enables corresponding support davix-libdir DavIx support, location of libdavix dcap-incdir dCache support, location of dcap.h dcap-libdir dCache support, location of libdcap + dicttype dictionary type: "cint" (default), "reflex", or "gccxml" dnssd-libdir Bonjour support, location of libdns_sd dnssd-incdir Bonjour support, location of dns_sd.h finkdir Prefix of extra MacOS X package manager (Fink, MacPorts, ...) @@ -1749,8 +1749,6 @@ with options, prefix with --with-, enables corresponding support monalisa-libdir Monalisa support, location of libapmoncpp mysql-incdir MySQL support, location of mysql.h mysql-libdir MySQL support, location of libmysqlclient - occ-incdir GEOCAD support, location of OpenCascade inc files - occ-libdir GEOCAD support, location of OpenCascade lib files odbc-incdir ODBC support, location of sqlext.h odbc-libdir ODBC support, location of libiodbc or libodbc opengl-incdir OpenGL support, location of GL/gl.h @@ -1799,8 +1797,6 @@ with compiler options, prefix with --with-, overrides default value cxx alternative C++ compiler and options to be used f77 alternative Fortran compiler and options to be used ld alternative Linker and options to be used - gcc-toolchain directory where gcc is installed (needed for compilation - of clang/LLVM in case not the default gcc is used) clang use clang compiler instead of gcc (mutual exclusive with the cc, cxx and ld options) @@ -1877,13 +1873,18 @@ fi platform=`grep "^PLATFORM *=" ${ac_srcdir}/config/Makefile.$arch | awk '{ print $3 }'` case $arch in -linuxppc64*) +sgicc) + logmsg "Will check 32bit libraries" + checklib32="yes" ;; +linuxppc64*|sgicc64) logmsg "Will ONLY check 64bit libraries" checkonlylib64="yes" ;; linuxx8664k1om*) logmsg "Will not check 64bit libraries" checklinux64="no" checklib64="no" + enable_cintex="no" + enable_reflex="no" enable_genvector="no" enable_tmva="no" ;; @@ -1891,9 +1892,6 @@ linuxx8664*) logmsg "Will check 64bit libraries" checklinux64="yes" checklib64="yes" ;; -linuxx32*) - logmsg "Will check x32 libraries in the future" - logmsg "For now expect proper libraries through configure flags" ;; hpuxia64acc) logmsg "Will check HP/UX 64bit libraries" checkhpux64="yes" ;; @@ -1925,7 +1923,7 @@ ios*) ios7=yes fi xcodepath=`/usr/bin/xcode-select -print-path` - if test "x$arch" = "xios" || test "x$arch" = "xios64"; then + if test "x$arch" = "xios"; then iossdk=$xcodepath/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$iosvers.sdk else iossdk=$xcodepath/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$iosvers.sdk @@ -1940,9 +1938,10 @@ ios*) # make available to conftest.mk scripts export IOSSDK=$iossdk export IOSVERS=$iosvers + enable_cintex="no" + enable_reflex="no" enable_genvector="no" enable_tmva="no" - enable_vdt="no" ;; win32) logmsg "Will use by default builtin versions of libraries on Win32" @@ -1983,9 +1982,6 @@ if test "x$platform" = "xmacosx" ; then if [ `sw_vers | sed -n 's/ProductVersion://p' | cut -d . -f 2` -ge 6 ]; then macosx106=yes fi - if [ `sw_vers | sed -n 's/ProductVersion://p' | cut -d . -f 2` -ge 7 ]; then - macosx107=yes - fi if [ `sw_vers | sed -n 's/ProductVersion://p' | cut -d . -f 2` -ge 8 ]; then macosx108=yes fi @@ -2080,11 +2076,15 @@ if test $# -gt 0 ; then --with-cern-libdir=*) echo "WARNING: option $1 is deprecated and ignored"'!' ;; --with-chirp-incdir=*) chirpincdir=$optarg ; enable_chirp="yes" ;; --with-chirp-libdir=*) chirplibdir=$optarg ; enable_chirp="yes" ;; + --with-cint-maxstruct=*) cintmaxstruct=$optarg ;; + --with-cint-maxtypedef=*) cintmaxtypedef=$optarg;; + --with-cint-longline=*) cintlongline=$optarg ;; --with-cppunit=*) cppunit=$optarg ;; --with-davix-incdir=*) davixincdir=$optarg ; enable_davix="yes" ;; --with-davix-libdir=*) davixlibdir=$optarg ; enable_davix="yes" ;; --with-dcap-incdir=*) dcapincdir=$optarg ; enable_dcache="yes" ;; --with-dcap-libdir=*) dcaplibdir=$optarg ; enable_dcache="yes" ;; + --with-dicttype=*) dicttype=$optarg ;; --with-dnssd-incdir=*) dnssdincdir=$optarg ; enable_bonjour="yes" ;; --with-dnssd-libdir=*) dnssdlibdir=$optarg ; enable_bonjour="yes" ;; --with-avahi-incdir=*) avahiincdir=$optarg ; enable_bonjour="yes" ;; @@ -2107,11 +2107,8 @@ if test $# -gt 0 ; then --with-gsl-incdir=*) gslincdir=$optarg ; enable_gsl="yes" ;; --with-gsl-libdir=*) gsllibdir=$optarg ; enable_gsl="yes" ;; --with-globus=*) globusdir=$optarg ; enable_globus="yes" ;; - --with-globus-incdir=*) globusincdir=$optarg ; enable_globus="yes" ;; - --with-globus-libdir=*) globuslibdir=$optarg ; enable_globus="yes" ;; - --with-geocad=*) geocaddir=$optarg ; enable_geocad="yes" ;; - --with-occ-incdir=*) occincdir=$optarg ; enable_geocad="yes" ;; - --with-occ-libdir=*) occlibdir=$optarg ; enable_geocad="yes" ;; + --with-globus-incdir=*) globusincdir=$optarg ; enable_globus="yes" ;; + --with-globus-libdir=*) globuslibdir=$optarg ; enable_globus="yes" ;; --with-gccxml=*) gccxml=$optarg ;; --with-hdfs-incdir=*) hdfsincdir=$optarg ; enable_hdfs="yes" ;; --with-hdfs-libdir=*) hdfslibdir=$optarg ; enable_hdfs="yes" ;; @@ -2123,7 +2120,7 @@ if test $# -gt 0 ; then --with-krb5-libdir=*) krb5libdir=$optarg ; enable_krb5="yes" ;; --with-ldap-incdir=*) ldapincdir=$optarg ; enable_ldap="yes" ;; --with-ldap-libdir=*) ldaplibdir=$optarg ; enable_ldap="yes" ;; - --with-llvm-config=*) llvmconfig=$optarg ; enable_builtin_llvm=no;; + --with-llvm-config=*) llvmconfig=$optarg ;; # require explicit --enable-cling --with-macosxvers=*) macosxvers=$optarg ;; --with-mysql-incdir=*) mysqlincdir=$optarg ; enable_mysql="yes" ;; --with-mysql-libdir=*) mysqllibdir=$optarg ; enable_mysql="yes" ;; @@ -2171,11 +2168,10 @@ if test $# -gt 0 ; then --with-xrootd=*) xrootddir=$optarg ; enable_xrootd="yes" ;; --with-xrootd-incdir=*) xrdincdir=$optarg ; enable_xrootd="yes" ;; --with-xrootd-libdir=*) xrdlibdir=$optarg ; enable_xrootd="yes" ;; - --with-cc=*) altcc=$optarg ; altccset=1 ;; + --with-cc=*) altcc=$optarg ;; --with-cxx=*) altcxx=$optarg ;; --with-f77=*) altf77=$optarg ;; --with-ld=*) altld=$optarg ;; - --with-gcc-toolchain=*) gcctoolchain=$optarg ;; --with-clang) altcc=clang; altcxx=clang++; altld=clang++ ;; --with-hostcc=*) hostcc=$optarg ;; --with-hostcxx=*) hostcxx=$optarg ;; @@ -2189,27 +2185,26 @@ if test $# -gt 0 ; then f=`echo $1 | sed -e 's/--//' -e 's/-/_/g' -e 's/++11/xx11/'` eval prev='$'`echo ${f}` eval prev_expl='$'`echo ${f}_explicit` + if test "${prev}:${prev_expl}" = "yes:"; then + echo "INFO: $1: already enabled by default." + fi if test ! "x`echo ${deprecated_options} | grep ${f}`" = "x"; then echo "WARNING: option $1 is deprecated and ignored"'!' - else - if test "${prev}:${prev_expl}" = "yes:"; then - echo "INFO: $1: already enabled by default." - fi - if test "x${prev_expl}" = "xno"; then - echo "WARNING: conflicting --disable / $1, $1 wins" - fi - eval ${f}=yes - eval ${f}_explicit=yes fi + if test "x${prev_expl}" = "xno"; then + echo "WARNING: conflicting --disable / $1, $1 wins" + fi + eval ${f}=yes + eval ${f}_explicit=yes for c in $options ; do if test "x$c" = "x$f" ; then f="" - fi + fi done for c in $deprecated_options ; do if test "x$c" = "x$f" ; then f="" - fi + fi done if test "x$f" != "x" ; then echo "Invalid option '$1'. Try $0 --help" ; exit 1 ; @@ -2219,28 +2214,19 @@ if test $# -gt 0 ; then f=`echo $1 | sed -e 's/--disable/enable/' -e 's/-/_/g' -e 's/++11/xx11/'` eval prev='$'`echo ${f}` eval prev_expl='$'`echo ${f}_explicit` - if test ! "x`echo ${deprecated_options} | grep ${f}`" = "x"; then - echo "WARNING: option $1 is deprecated and ignored"'!' - else - if test "${prev}:${prev_expl}" = "xno:"; then - echo "INFO: $1: already disabled by default." - fi - if test "x${prev_expl}" = "xyes"; then - echo "WARNING: conflicting --enable / $1, $1 wins" - fi - eval ${f}=no - eval ${f}_explicit=no + if test "${prev}:${prev_expl}" = "xno:"; then + echo "INFO: $1: already disabled by default." + fi + if test "x${prev_expl}" = "xyes"; then + echo "WARNING: conflicting --enable / $1, $1 wins" fi + eval ${f}=no + eval ${f}_explicit=no for c in $options ; do if test "x$c" = "x$f" ; then f="" fi done - for c in $deprecated_options ; do - if test "x$c" = "x$f" ; then - f="" - fi - done if test "x$f" != "x" ; then echo "Invalid option '$1'. Try $0 --help" ; exit 1 ; fi @@ -2256,6 +2242,7 @@ if test $# -gt 0 ; then # --aclocaldir=*) haveconfig=-DR__HAVE_CONFIG ; aclocaldir=$optarg ;; --bindir=*) haveconfig=-DR__HAVE_CONFIG ; bindir=$optarg ;; + --cintincdir=*) haveconfig=-DR__HAVE_CONFIG ; cintincdir=$optarg ;; --datadir=*) haveconfig=-DR__HAVE_CONFIG ; datadir=$optarg ;; --docdir=*) haveconfig=-DR__HAVE_CONFIG ; docdir=$optarg ;; --elispdir=*) haveconfig=-DR__HAVE_CONFIG ; elispdir=$optarg ;; @@ -2464,15 +2451,6 @@ if test $found_comp -eq 0 ; then altf77= fi -# the path for the gcctoolchain in case not the system gcc is used to -# build clang/LLVM. This path is used to build clang/LLVM. -if test "x$gcctoolchain" != "x"; then - if test "x$altccset" = "x" ; then - result "`basename $0`: no alternative gcc compiler specified, incompatible with --with-gcc-toolchain option" - exit 1 - fi -fi - ###################################################################### # ### echo %%% Check host environment in case of cross compiling @@ -2530,17 +2508,17 @@ if test "x$enable_cxx11" = "xyes"; then check_cxxopt -std=c++11 if test $cxxopt_result -eq 0 ; then enable_cxx11="no" - result "no" + result "no" result "`basename $0`: c++11 mode is requested but the current compiler does not support it." exit 1 else - usecxx11="define" + usecxx11="define" # on OS X libcxx is required for C++11 support with clang # so turn the option on when using clang if test "x$platform" = "xmacosx" && echo $altcxx | grep 'clang++' > /dev/null 2>&1; then enable_libcxx="yes" fi - result "yes" + result "yes" fi fi @@ -2572,69 +2550,6 @@ if test "x$enable_libcxx" = "xyes" ; then fi fi -###################################################################### -# -### echo %%% Check for linker's support of --no-ctors-in-init-array -# -### This changes the sequence for static initialization to be right -### to left. -# -logmsg "Derminining support for --no-ctors-in-init-array" -cat < conftest.mk -include ${ac_srcdir}/config/Makefile.${arch} -CC = ${altcc} -CXX = ${altcxx} -LD = ${altld} -conftest: conftest.cxx - \$(CC) \$(LDFLAGS) -Wl,--no-ctors-in-init-array \$^ -o \$@ - -conftest.cxx: - echo 'int main(int,char*[]){return 0;}' >> \$@ -EOF -$gnumake -f conftest.mk >> $logfile 2>&1 -if test $? -eq 0 ; then - logmsg " supported" - ctorsinitarray="yes" -else - logmsg " not supported" - ctorsinitarray="no" -fi -rm -f conftest.mk conftest conftest.cxx - -###################################################################### -# -### echo %%% Check for builtin or external LLVM/Clang -# -hasllvm="undef" -llvmdir="/**/" -if test "x$enable_builtin_llvm" = "x" || \ - test "x$enable_builtin_llvm" = "xno" ; then - message "Checking for llvm-config for external llvm" - # allow LLVMDIR instead of --with-llvm-config - if test "x$llvmconfig" = "x" ; then - if test ! "x$LLVMDIR" = "x" ; then - llvmconfig="$LLVMDIR/bin" - fi - fi - if test ! "x$llvmconfig" = "x"; then - if test -d "$llvmconfig"; then - llvmconfig=$llvmconfig/llvm-config - fi - if test -f $llvmconfig && test -x $llvmconfig; then - hasllvm="define" - llvmdir="`dirname $llvmconfig`" - llvmdir='"'"`dirname $llvmdir`"'"' - fi - fi - if test "x$hasllvm" = "xundef"; then - enable_builtin_llvm="yes" - llvmconfig="" - result "no (needs --with-llvm-config or \$LLVMDIR)" - else - result "$llvmconfig" - fi -fi - ###################################################################### # ### echo %%% Check if native MacOS X Cocoa/Quartz backend should be build @@ -2642,7 +2557,7 @@ fi if test ! "x$platform" = "xmacosx"; then enable_cocoa="no" fi -if test "x$macosx107" = "xyes" && test "x$enable_cocoa" = "x"; then +if test "x$macosx108" = "xyes" && test "x$enable_cocoa" = "x"; then enable_cocoa="yes" fi if test "x$enable_cocoa" = "x"; then @@ -3093,8 +3008,8 @@ if test ! "x$enable_opengl" = "xno" && test ! "x$platform" = "xwin32" ; then opengllibdir=$found_dir if test ! "x$macosx105" = "x" && test "x$macosx106" = "x" ; then - # Mac OS X 10.5 problem - opengllib="-dylib_file /usr/X11R6/lib/libGL.dylib:/usr/X11R6/lib/libGL.dylib -lGL" + # Mac OS X 10.5 problem + opengllib="-dylib_file /usr/X11R6/lib/libGL.dylib:/usr/X11R6/lib/libGL.dylib -lGL" fi skipchecklibcxxcompat="yes" @@ -3338,7 +3253,7 @@ if test ! "x$enable_oracle" = "xno"; then $ORACLE ${ORACLE:+$ORACLE/lib} $ORACLELIBDIR \ /usr/local/lib /usr/lib /usr/lib/oracle/*/client/lib if test "x$found_lib" = "x"; then - oraclelib="" + oraclelib="" elif test ! "x$oraclelib" = "x"; then oraclelib="$oraclelib $found_lib" fi @@ -3410,8 +3325,8 @@ if test ! "x$enable_sqlite" = "xno"; then /usr/include /usr/local/include \ /usr/include/sqlite /usr/local/include/sqlite /usr/local/sqlite/include \ /usr/include/sqlite3 /usr/local/include/sqlite3 /usr/local/sqlite3/include \ - /usr/sqlite /opt/sqlite /opt/sqlite3/include \ - /usr/sqlite3 /opt/sqlite3 /opt/sqlite/include + /usr/sqlite /opt/sqlite /opt/sqlite3/include \ + /usr/sqlite3 /opt/sqlite3 /opt/sqlite/include sqliteinc=$found_hdr sqliteincdir=$found_dir @@ -3582,7 +3497,7 @@ if test ! "x$enable_qt" = "xno" || \ qtincdir="$qtincdir $i" fi done - qtverneed="4.8.0" + qtverneed="4.3.0" qttoonew="5.0.0" qttestdir=$qtmainincdir/../src/corelib/global if test ! -d $qttestdir ; then @@ -3676,7 +3591,7 @@ if test ! "x$enable_rfio" = "xno" ; then $RFIO ${RFIO:+$RFIO/include} \ ${RFIO:+$RFIO/include/shift} ${RFIO:+$RFIO/h} \ /cern/pro/include /cern/new/include /cern/old/include \ - /opt/shift/include /usr/local/shift/inlcude /usr/include/shift \ + /opt/shift/include /usr/local/shift/include /usr/include/shift \ /usr/local/include/shift /usr/include /usr/local/include shiftinc=$found_hdr shiftincdir=$found_dir @@ -3751,7 +3666,7 @@ if test ! "x$enable_castor" = "xno" ; then $CASTOR ${CASTOR:+$CASTOR/include} \ ${CASTOR:+$CASTOR/include/shift} ${CASTOR:+$CASTOR/h} \ /cern/pro/include /cern/new/include /cern/old/include \ - /opt/shift/include /usr/local/shift/inlcude /usr/include/shift \ + /opt/shift/include /usr/local/shift/include /usr/include/shift \ /usr/local/include/shift /usr/include /usr/local/include castorinc=$found_hdr castorincdir=$found_dir @@ -3773,7 +3688,7 @@ if test ! "x$enable_castor" = "xno" ; then $CASTOR ${CASTOR:+$CASTOR/include} \ ${CASTOR:+$CASTOR/include/shift} ${CASTOR:+$CASTOR/h} \ /cern/pro/include /cern/new/include /cern/old/include \ - /opt/shift/include /usr/local/shift/inlcude /usr/include/shift \ + /opt/shift/include /usr/local/shift/include /usr/include/shift \ /usr/local/include/shift /usr/include /usr/local/include stagerinc=$found_hdr @@ -4529,17 +4444,13 @@ if test ! "x$enable_asimage" = "xno" ; then fi # If we didn't find the system libAfterImage, or the user didn't ask # for a system library, then see if we have various headers needed. - # For Cocoa backend force libAfterImage builtin jpeg and png libs - # to avoid system versions based on X11. if test "x$enable_builtin_afterimage" = "xyes" && test ! "x$enable_cocoa" = "xyes"; then check_header "jpeglib.h" "" \ - ${LIBJPEG:+$LIBJPEG/include} \ $ASIMAGE ${ASIMAGE:+$ASIMAGE/include} \ ${finkdir:+$finkdir/include} \ /usr/local/include /usr/include /opt/include asjpegincdir=$found_dir check_header "png.h" "" \ - ${LIBPNG:+$LIBPNG/include} \ $ASIMAGE ${ASIMAGE:+$ASIMAGE/include} \ ${ASPNG:+$ASPNG/include} \ ${finkdir:+$finkdir/include} \ @@ -4548,7 +4459,6 @@ if test ! "x$enable_asimage" = "xno" ; then aspngincdir=$found_dir if test ! "x$enable_astiff" = "xno" ; then check_header "tiffio.h" "" \ - ${LIBTIFF:+$LIBTIFF/include} \ $ASIMAGE ${ASIMAGE:+$ASIMAGE/include} \ ${finkdir:+$finkdir/include} \ /usr/local/include /usr/include /opt/include @@ -4570,8 +4480,6 @@ if test ! "x$enable_asimage" = "xno" ; then fi for k in $aslibs ; do check_library $k "$enable_shared" "" \ - ${LIBJPEG:+$LIBJPEG/lib} ${LIBPNG:+$LIBPNG/lib} \ - ${LIBTIFF:+$LIBTIFF/lib} ${ZLIB:+$ZLIB/lib} \ $ASIMAGE ${ASIMAGE:+$ASIMAGE/lib} ${ASPNG:+$ASPNG/lib} \ ${finkdir:+$finkdir/lib} \ /usr/local/lib /usr/X11/lib /usr/lib /opt/lib @@ -4608,39 +4516,6 @@ fi check_explicit "$enable_asimage" "$enable_asimage_explicit" \ "Explicitly required AfterImage dependencies not fulfilled" -###################################################################### -# -### echo %%% GEOCAD Library - Contributed library -# -# (See http://www.opencascade.org/) -# -# If the user has set the flags "--disable-geocad", we don't check for -# OpenCascade at all. -# -if test ! "x$enable_geocad" = "xno"; then - # Check for OpenCascade include and library - check_header "XCAFApp_Application.hxx" "$occincdir" \ - $CASROOT ${CASROOT:+$CASROOT/inc} /usr/include/opencascade \ - /usr/include - occinc=$found_hdr - occincdir=$found_dir - - check_library "libTKXCAF" "$enable_shared" "$occlibdir" \ - $CASROOT ${CASROOT:+$CASROOT/lib} /usr/lib - occlib=$found_lib - occlibdir=$found_dir - - if test ! "x$occlib" = "x" ; then - occlib="-lTKPrim -lTKBRep -lTKOffset -lTKGeomBase -lTKShHealing -lTKTopAlgo -lTKSTEP -lTKG2d -lTKBool -lTKBO -lTKXCAF -lTKXDESTEP -lTKLCAF -lTKernel -lTKXSBase -lTKG3d -lTKMath" - fi - - if test "x$occincdir" = "x" || test "x$occlib" = "x"; then - enable_geocad="no" - fi -fi -check_explicit "$enable_geocad" "$enable_geocad_explicit" \ - "Explicitly required GeoCad dependencies not fulfilled" - ###################################################################### # ### echo %%% LDAP Support - Third party libraries @@ -4696,11 +4571,6 @@ check_explicit "$enable_ldap" "$enable_ldap_explicit" \ # # (See http://www.python.org) # -if test ! "x$enable_python" = "xno" ; then - # PyROOT depends on cling - message "Checking for PyROOT prerequisites" - result "yes" -fi if test ! "x$enable_python" = "xno" ; then # Check for Python include and library mypython=`$cwhich python 2> /dev/null` @@ -5029,7 +4899,7 @@ if test "x$enable_xrootd" = "xyes" ; then fi if test "x$oldver" = "xyes" ; then decver=`echo $tmpver | sed 's|[^0-9]||g' | cut -c1-8` - fi + fi fi fi # Protect against 3.3.0, first version with 'include/xrootd/private' @@ -6100,6 +5970,16 @@ fi check_explicit "$enable_krb5" "$enable_krb5_explicit" \ "Explicitly required Kerberos5 dependencies not fulfilled" +###################################################################### +# +### echo %%% libcmaes support - Third party libraries +check_header "cmaes.h" "/home/beniz/research/siminole/dev/libcmaes/src" /usr/include +cmaesinc=$found_hdr +cmaesincdir=$found_dir +check_library "libcmaes" "yes" "/home/beniz/research/siminole/dev/libcmaes/src/.libs" /usr/lib +cmaeslib=$found_lib +cmaeslibdir=$found_dir + ###################################################################### # ### echo %%% Communication of errors library @@ -6319,6 +6199,7 @@ sed -e "s|@avxcxxflag@|$avxcxxflag|" \ < Makefile.tmp > Makefile.tmpp mv Makefile.tmpp Makefile.tmp + ###################################################################### # ### echo %%% MathMore Library - Contributed library @@ -6337,11 +6218,11 @@ if test ! "x$enable_mathmore" = "xno"; then ${finkdir:+$finkdir/include} \ /usr/local/include /usr/include /opt/gsl/include - # check for gsl version >= 1.10 + # check for gsl version >= 1.8 if test ! "x$found_dir" = "x"; then - message "Checking for GSL version >= 1.10" - gsl_version=`grep "define GSL_VERSION" $found_dir/gsl/gsl_version.h | sed 's/^.*"\([0-9]\..*[0-9]\)"/\1/' | awk 'BEGIN { FS="." } { printf "%d", $1 * 1000 + $2 }'` - if test $gsl_version -lt 1010; then + message "Checking for GSL version >= 1.8" + gsl_version=`grep "define GSL" $found_dir/gsl/gsl_version.h | sed 's/^.*"\([0-9]\..*[0-9]\)"/\1/' | awk 'BEGIN { FS="." } { printf "%d", $1 * 1000 + $2 }'` + if test $gsl_version -lt 1008; then gslskip="skip" result "no" enable_mathmore="no" @@ -6504,6 +6385,49 @@ fi check_explicit "$enable_genvector" "$enable_genvector_explicit" \ "Explicitly required GenVector dependencies not fulfilled" +###################################################################### +# +### echo %%% Cintex Library - Contributed library +# +message "Checking whether to build libCintex" +if test ! "x$enable_cintex" = "xno"; then + # only enable on i386, i686, x86_64: + case "$chip" in + i*86 | x86_64) + enable_cintex="yes" + result "yes" + ;; + *) + case `uname -m` in + i*86 | x86_64) + enable_cintex="yes" + result "yes" + ;; + *) + logmsg " incompatible Cintex architecture $chip" + enable_cintex="" + result "no" + ;; + esac + esac +else + enable_cintex="" + result "no" +fi + +###################################################################### +# +### echo %%% Reflex Library - Contributed library +# +message "Checking whether to build libReflex" +if test ! "x$enable_reflex" = "xno"; then + enable_reflex="yes" + result "yes" +else + enable_reflex="" + result "no" +fi + ###################################################################### # ### echo %%% RooFit Library - Contributed library @@ -6530,6 +6454,19 @@ else result "no" fi +###################################################################### +# +### echo %%% CMAES Library - Contributed library +# +message "Checking whether to build libcmaes" +if test "x$enable_cmaes" = "xyes" || test ! "x$CMAES" = "x"; then + enable_cmaes="yes" + result "yes" +else + enable_cmaes="" + result "no" +fi + ###################################################################### # ### echo %%% Unuran Library - Contributed library @@ -6557,6 +6494,7 @@ else result "no" hasvc="undef" fi + ###################################################################### # ### echo %%% VDT Library - Contributed library @@ -6572,6 +6510,7 @@ else hasvdt="undef" fi + ###################################################################### # ### echo %%% GDML Library - Contributed library @@ -6668,6 +6607,78 @@ else fi result "$enable_afdsmgrd$afdsmgrdapmonmsg" +###################################################################### +# +### echo %%% Cling - LLVM/clang based interpreter prototype +# +message "Checking whether to integrate experimental cling" +hascling="undef" +clingextrares="" +if test ! "x$enable_cling" = "xno"; then + # allow LLVMDIR instead of --with-llvm-config + if test "x$llvmconfig" = "x" ; then + if test ! "x$LLVMDIR" = "x" ; then + llvmconfig="$LLVMDIR/bin" + else + clingextrares="(needs --with-llvm-config or \$LLVMDIR)" + fi + result "no" + fi + if test ! "x$llvmconfig" = "x"; then + if test -d "$llvmconfig"; then + llvmconfig=$llvmconfig/llvm-config + fi + if test -f $llvmconfig && test -x $llvmconfig; then + hascling="define" + fi + fi +fi +if test "x$hascling" = "xundef"; then + enable_cling="no" + result "no $clingextrares" +else + enable_cling="yes" + result "yes" +fi + +###################################################################### +# +### echo %%% What dictionaries to build +# +# Can be either CINT (default), reflex, or gccxml. +# Option will be passed to rootcint(_tmp), +# and root-config --libs will have -lReflex if needed. +# +message "Checking what type of dictionaries to build" +# --with-dicttype overrides env var ROOTDICTTYPE +if test "x$dicttype" = "x" ; then + dicttype="$ROOTDICTTYPE" +fi + +# set default to CINT +if test "x$dicttype" = "x"; then + dicttype=cint +fi + +case "$dicttype" in + cint);; + reflex | gccxml) + # check that cintex is enabled for reflex/gccxml + if test ! "x$enable_cintex" = "xyes"; then + result "Cannot generate $dicttype dictionaries with cintex disabled." + dicttype=cint + fi ;; + *) + result "Unknown dictionary \"$dicttype\"." + result " Must be one of cint, reflex, gccxml." + dicttype=cint + ROOTDICTTYPE="trigger print info" + ;; +esac + +# Print info if dicttype!=cint, or --with-dict overrides $ROOTDICTTYPE +result "$dicttype" + ###################################################################### # ### echo %%% Debian or Red Hat package list @@ -6690,7 +6701,6 @@ if test "x$show_pkglist" = "xyes" ; then test "x$enable_roofit" = "xyes" && pl="$pl libroot-roofit" test "x$enable_asimage" = "xyes" && pl="$pl root-plugin-graf2d-asimage" test "x$enable_gdml" = "xyes" && pl="$pl root-plugin-geom-gdml" - test "x$enable_geocad" = "xyes" && pl="$pl root-plugin-geom-geocad" test "x$enable_qt" = "xyes" && pl="$pl root-plugin-gui-qt root-plugin-graf2d-qt" test "x$enable_castor" = "xyes" && pl="$pl root-plugin-io-castor" test "x$enable_chirp" = "xyes" && pl="$pl root-plugin-io-chirp" @@ -6703,6 +6713,7 @@ if test "x$show_pkglist" = "xyes" ; then test "x$enable_fitsio" = "xyes" && pl="$pl root-plugin-graf2d-fitsio" test "x$enable_gviz" = "xyes" && pl="$pl root-plugin-graf2d-gviz" test "x$enable_minuit2" = "xyes" && pl="$pl root-plugin-math-minuit2" + test "x$enable_cmaes" = "xyes" && pl="$pl root-plugin-math-cmaes" test "x$enable_pythia6" = "xyes" && pl="$pl root-plugin-montecarlo-pythia6" test "x$enable_alien" = "xyes" && pl="$pl root-plugin-net-alien" test "x$enable_bonjour" = "xyes" && pl="$pl root-plugin-net-bonjour" @@ -6730,6 +6741,7 @@ if test "x$show_pkglist" = "xyes" ; then libroot-hist \ libroot-hist-spectrum \ libroot-io \ + libroot-math-cmaes \ libroot-math-foam \ libroot-math-genvector \ libroot-math-mathcore \ @@ -6857,18 +6869,9 @@ fi if test -d star ; then rm -rf star fi -if test -d cint ; then - rm -rf cint -fi if test -d include/cint ; then rm -rf include/cint fi -if test -d include/Cintex ; then - rm -rf include/Cintex -fi -if test -d include/Reflex ; then - rm -rf include/Reflex -fi if test -d graf2d/freetype/src/freetype-2.3.5 ; then rm -rf graf2d/freetype/src/freetype-2.3.5 fi @@ -6899,9 +6902,6 @@ fi if test -d core/editline ; then rm -rf core/editline fi -if test -d core/globals ; then - rm -rf core/globals -fi if test -d net/xrootd ; then rm -rf net/xrootd fi @@ -6914,9 +6914,10 @@ fi rm -f lib/libRXML* bin/libRXML* etc/system.rootmap \ etc/svninfo.txt lib/libProofGui* bin/libProofGui* \ lib/libMySQL* bin/libMySQL* lib/libGedOld* bin/libGedOld* \ - lib/libSQL.* bin/libSQL.* core/utils/src/rootcint_tmp \ + lib/libSQL.* bin/libSQL.* \ lib/libASPluginGS.* bin/g2rootold* bin/ptest main/src/ptest.* \ math/mathcore/src/G__MathCore32.* \ + tmva/src/G__TMVA.* graf3d/eve/src/G__Eve.* \ xrootd/src/headers.d include/Xpm.h \ asimage/src/headers.d asimage/src/G__ASImageGS.* \ core/utils/src/rootcint7.cxx core/utils/src/RStl7.cxx \ @@ -6924,68 +6925,13 @@ rm -f lib/libRXML* bin/libRXML* etc/system.rootmap \ core/metautils/src/RConversionRuleParser7.cxx \ core/meta/src/G__TCint.h core/meta/src/G__TCint.cxx \ core/thread/src/TLockFile.* proof/proofplayer/src/TFileMerger.* \ - core/base/src/ManualBase4.* tree/tree/src/ManualTree2.* \ graf2d/graf/src/G__Graf1.h graf2d/graf/src/G__Graf1.cxx \ graf2d/graf/src/G__Graf2.h graf2d/graf/src/G__Graf2.cxx \ - core/base/src/G__Base1.h core/base/src/G__Base2.h \ - core/base/src/G__Base3.h core/clib/src/G__Clib.h \ - core/cont/src/G__Cont.h core/macosx/src/G__Macosx.h \ - core/meta/src/G__Meta.h core/metautils/src/G__MetaUtils.h \ - core/textinput/src/G__TextInput.h core/unix/src/G__Unix.h \ - core/zip/src/G__Zip.h geom/geom/src/G__Geom1.h \ - geom/geom/src/G__Geom2.h graf3d/g3d/src/G__G3D.h \ - graf3d/gl/src/G__GL.h gui/gui/src/G__Gui1.h \ - gui/gui/src/G__Gui2.h gui/gui/src/G__Gui3.h \ - graf2d/x11ttf/src/G__X11TTF.h graf2d/x11/src/G__X11.cxx \ - graf3d/x3d/src/G__X3D.h \ - hist/spectrumpainter/src/G__Spectrum2Painter.h \ - io/io/src/G__IO.h io/sql/src/G__SQL.h io/xml/src/G__XML.h \ - math/mathcore/src/G__Math.h math/mathcore/src/G__MathFit.h \ - net/ldap/src/G__LDAP.h core/winnt/src/G__WinNT.h \ - graf3d/eve/src/G__Eve1.h graf3d/eve/src/G__Eve2.h \ - tmva/src/G__TMVA1.h tmva/src/G__TMVA2.h tmva/src/G__TMVA3.h \ - tmva/src/G__TMVA4.h roofit/roofitcore/src/G__RooFitCore1.h \ - roofit/roofitcore/src/G__RooFitCore2.h roofit/roofitcore/src/G__RooFitCore3.h \ - roofit/roofitcore/src/G__RooFitCore4.h \ - core/base/src/G__Base1.cxx core/base/src/G__Base2.cxx \ - core/base/src/G__Base3.cxx core/clib/src/G__Clib.cxx \ - core/cont/src/G__Cont.cxx core/macosx/src/G__Macosx.cxx \ - core/meta/src/G__Meta.cxx core/metautils/src/G__MetaUtils.cxx \ - core/textinput/src/G__TextInput.cxx core/unix/src/G__Unix.cxx \ - core/zip/src/G__Zip.cxx geom/geom/src/G__Geom1.cxx \ - geom/geom/src/G__Geom2.cxx graf3d/g3d/src/G__G3D.cxx \ - graf3d/gl/src/G__GL.cxx gui/gui/src/G__Gui1.cxx \ - gui/gui/src/G__Gui2.cxx gui/gui/src/G__Gui3.cxx \ - hist/spectrumpainter/src/G__Spectrum2Painter.cxx \ - io/io/src/G__IO.cxx io/sql/src/G__SQL.cxx io/xml/src/G__XML.cxx \ - math/mathcore/src/G__Math.cxx math/mathcore/src/G__MathFit.cxx \ - net/ldap/src/G__LDAP.cxx core/winnt/src/G__WinNT.cxx \ - graf3d/eve/src/G__Eve1.cxx graf3d/eve/src/G__Eve2.cxx \ - graf2d/x11ttf/src/G__X11TTF.cxx graf2d/x11/src/G__X11.cxx \ - graf3d/x3d/src/G__X3D.cxx \ - roofit/roofitcore/src/G__RooFitCore1.cxx \ - roofit/roofitcore/src/G__RooFitCore2.cxx \ - roofit/roofitcore/src/G__RooFitCore3.cxx \ - roofit/roofitcore/src/G__RooFitCore4.cxx \ - tmva/src/G__TMVA1.cxx tmva/src/G__TMVA2.cxx tmva/src/G__TMVA3.cxx \ - tmva/src/G__TMVA4.cxx \ net/net/src/TAS3File.* net/net/src/TGSFile.* net/net/src/THTTPMessage.* \ etc/daemons/olbd.rc.d etc/daemons/cmsd.rc.d etc/daemons/xrootd.rc.d \ bin/cmsd bin/xprep bin/xrd bin/xrdcp bin/xrdgsiproxy bin/xrdpwdadmin \ bin/xrdsssadmin bin/xrdstagetool bin/xrootd lib/libXrd* \ - bin/drop_from_path bin/genreflex bin/genreflex.bat bin/genreflex-rootcint \ - bin/genreflex-rootcint.bat lib/libcomplexDict.rootmap \ - lib/libdequeDict.rootmap lib/liblistDict.rootmap lib/libmap2Dict.rootmap \ - lib/libmapDict.rootmap lib/libmultimap2Dict.rootmap \ - lib/libmultimapDict.rootmap lib/libmultisetDict.rootmap \ - lib/libsetDict.rootmap lib/libvalarrayDict.rootmap lib/libvectorDict.rootmap \ - include/TListOfTypes.h lib/*_RootCling.rootmap bin/rlibmap - -# if previous build was in non-c++11 mode, run "make maintainer-clean" first -run_maintainer_clean="no" -if `grep '#undef R__USE_CXX11' $CONFIGUREOUT > /dev/null 2>&1` ; then - run_maintainer_clean="yes" -fi + bin/drop_from_path ###################################################################### # @@ -7034,6 +6980,7 @@ if test ! "x$haveconfig" = "x" ; then if test "x$mandir" = "x"; then mandir=$prefix/share/man/man1; fi if test "x$datadir" = "x"; then datadir=$prefix/share/root; fi if test "x$macrodir" = "x"; then macrodir=$datadir/macros; fi + if test "x$cintincdir" = "x"; then cintincdir=$libdir/cint; fi if test "x$iconpath" = "x"; then iconpath=$datadir/icons; fi if test "x$srcdir" = "x"; then srcdir=$datadir/src; fi if test "x$fontdir" = "x"; then fontdir=$datadir/fonts; fi @@ -7082,6 +7029,7 @@ else datadir=\$\(ROOTSYS\) mandir=\$\(ROOTSYS\)/man/man1 macrodir=\$\(ROOTSYS\)/macros + cintincdir=\$\(ROOTSYS\)/cint iconpath=\$\(ROOTSYS\)/icons srcdir=\$\(ROOTSYS\)/src fontdir=\$\(ROOTSYS\)/fonts @@ -7160,7 +7108,6 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@buildglew@|$enable_builtin_glew|" \ -e "s|@builtinfreetype@|$enable_builtin_freetype|" \ -e "s|@builtinpcre@|$enable_builtin_pcre|" \ - -e "s|@builtinllvm@|$enable_builtin_llvm|" \ -e "s|@hasxrd@|$enable_xrootd|" \ -e "s|@castorincdir@|$castorincdir|" \ -e "s|@castorlib@|$castorlib|" \ @@ -7169,6 +7116,10 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@chirpincdir@|$chirpincdir|" \ -e "s|@chirplib@|$chirplib|" \ -e "s|@chirplibdir@|$chirplibdir|" \ + -e "s|@cintmaxstruct@|$cintmaxstruct|" \ + -e "s|@cintmaxtypedef@|$cintmaxtypedef|" \ + -e "s|@cintlongline@|$cintlongline|" \ + -e "s|@cintincdir@|$cintincdir|" \ -e "s|@cppunit@|$cppunit|" \ -e "s|@datadir@|$datadir|" \ -e "s|@davixincdir@|$davixincdir|" \ @@ -7177,10 +7128,14 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@comerrlibdir@|$comerrlibdir|" \ -e "s|@cryptolib@|$cryptolib|" \ -e "s|@cryptolibdir@|$cryptolibdir|" \ + -e "s|@cmaeslibdir@|$cmaeslibdir|" \ + -e "s|@cmaeslib@|$cmaeslib|" \ + -e "s|@cmaesincdir@|$cmaesincdir|" \ -e "s|@davixlib@|$davixlib|" \ -e "s|@davixlibdir@|$davixlibdir|" \ -e "s|@dcaplib@|$dcaplib|" \ -e "s|@dcaplibdir@|$dcaplibdir|" \ + -e "s|@dicttype@|$dicttype|" \ -e "s|@docdir@|$docdir|" \ -e "s|@elispdir@|$elispdir|" \ -e "s|@buildgenvector@|$enable_genvector|" \ @@ -7203,13 +7158,16 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@lzmaincdir@|$lzmaincdir|" \ -e "s|@lzmalib@|$lzmalib|" \ -e "s|@lzmalibdir@|$lzmalibdir|" \ + -e "s|@buildcintex@|$enable_cintex|" \ + -e "s|@buildcling@|$enable_cling|" \ + -e "s|@buildreflex@|$enable_reflex|" \ -e "s|@buildroofit@|$enable_roofit|" \ -e "s|@buildminuit2@|$enable_minuit2|" \ + -e "s|@buildcmaes@|$enable_cmaes|" \ -e "s|@buildunuran@|$enable_unuran|" \ -e "s|@buildvc@|$enable_vc|" \ -e "s|@buildvdt@|$enable_vdt|" \ -e "s|@buildgdml@|$enable_gdml|" \ - -e "s|@buildgeocad@|$enable_geocad|" \ -e "s|@buildmonalisa@|$enable_monalisa|" \ -e "s|@buildtable@|$enable_table|" \ -e "s|@buildtmva@|$enable_tmva|" \ @@ -7226,7 +7184,6 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@glitelib@|$glitelib|" \ -e "s|@glitelibdir@|$glitelibdir|" \ -e "s|@gaw_cppflags@|$gaw_cppflags|" \ - -e "s|@ctorsinitarray@|$ctorsinitarray|" \ < Makefile.tmp > Makefile.tmpp mv Makefile.tmpp Makefile.tmp @@ -7278,9 +7235,6 @@ sed -e "s|@globusincdir@|$globusincdir|" \ -e "s|@mysqlincdir@|$mysqlincdir|" \ -e "s|@mysqllib@|$mysqllib|" \ -e "s|@mysqllibdir@|$mysqllibdir|" \ - -e "s|@occincdir@|$occincdir|" \ - -e "s|@occlib@|$occlib|" \ - -e "s|@occlibdir@|$occlibdir|" \ -e "s|@odbcincdir@|$odbcincdir|" \ -e "s|@odbclib@|$odbclib|" \ -e "s|@odbclibdir@|$odbclibdir|" \ @@ -7406,7 +7360,6 @@ sed -e "s|@srcdir@|$ac_srcdir|" \ -e "s|@buildnetxng@|$buildnetxng|" \ -e "s|@c++11@|$enable_cxx11|" \ -e "s|@libc++@|$enable_libcxx|" \ - -e "s|@werror@|$enable_werror|" \ < Makefile.tmp > $MAKEOUT rm -f Makefile.tmp @@ -7429,7 +7382,6 @@ sed -e "s|@altcc@|$altcc|" \ -e "s|@altcxx@|$altcxx|" \ -e "s|@altf77@|$altf77|" \ -e "s|@altld@|$altld|" \ - -e "s|@gcctoolchain@|$gcctoolchain|" \ < Makefile-comp.tmp > $MAKECOMPOUT rm -f Makefile-comp.tmp @@ -7442,6 +7394,7 @@ message "Writing $CONFIGUREOUT" sed \ -e "s|@architecture@|$arch|" \ -e "s|@bindir@|$bindir|" \ + -e "s|@cintincdir@|$cintincdir|" \ -e "s|@datadir@|$datadir|" \ -e "s|@docdir@|$docdir|" \ -e "s|@etcdir@|$etcdir|" \ @@ -7457,19 +7410,18 @@ sed \ -e "s|@hasmathmore@|$hasmathmore|" \ -e "s|@haspthread@|$haspthread|" \ -e "s|@hasxft@|$hasxft|" \ + -e "s|@hascling@|$hascling|" \ -e "s|@hascocoa@|$hascocoa|" \ -e "s|@hasvc@|$hasvc|" \ -e "s|@usec++11@|$usecxx11|" \ -e "s|@uselibc++@|$uselibcxx|" \ - -e "s|@hasllvm@|$hasllvm|" \ - -e "s|@llvmdir@|$llvmdir|" \ < RConfigure.tmp > RConfigure-out.tmp rm -f RConfigure.tmp # only update $CONFIGUREOUT when different if test -f $CONFIGUREOUT; then diff RConfigure-out.tmp $CONFIGUREOUT > /dev/null; status=$?; - if [ "$status" -ne "0" ] && [ "x$run_maintainer_clean" = "xno" ]; then + if [ "$status" -ne "0" ]; then mv -f RConfigure-out.tmp $CONFIGUREOUT else rm -f RConfigure-out.tmp @@ -7578,6 +7530,7 @@ sed -e "s|@architecture@|$arch|" \ -e "s|@features@|$features|" \ -e "s|@winrtdebug@|$enable_winrtdebug|"\ -e "s|@configargs@|$configargs|" \ + -e "s|@dicttype@|$dicttype|" \ -e "s|@pythonvers@|$pythonvers|" \ -e "s|@alloclibdir@|$alloclibdir|" \ -e "s|@alloclib@|$alloclib|" \ @@ -7772,6 +7725,60 @@ else result "done" fi +#--------------------------------------------------------------------- +# bin/genreflex(.bat), bin/genreflex-rootcint(.bat) +# +if test "x$enable_reflex" = "xyes"; then + libdirreflex=$libdir + if test "x$haveconfig" = "x" ; then + libdirreflex='$0; if readlink $dir > /dev/null 2>\&1; then lndir=`readlink $dir`; dir=`dirname $dir`; lndir=`dirname $lndir`; dir=`cd $dir \&\& cd $lndir \&\& pwd \|\| echo $lndir`; else dir=`dirname ${dir}`; fi; dir=${dir}/../lib' + fi + modpath="" + if test "x$platform" = "xwin32"; then + modpath=';dir=`cygpath -m $dir`' + fi + + message "Writing $GENREFLEXSHOUT" + cat $GENREFLEXSHIN | sed -e "s|@libdir@|$libdirreflex$modpath|g" > $GENREFLEXSHOUT + chmod a+x $GENREFLEXSHOUT + result "done" + if test "x$platform" = "xwin32"; then + message "Writing $GENREFLEXBATOUT" + if test "x$haveconfig" = "x" ; then + libdirreflex='%~d0%~p0\\..\\lib' + else + libdirreflex=`cygpath -m $libdir` + fi + + cat $GENREFLEXBATIN | sed -e "s|@libdir@|$libdirreflex|g" > $GENREFLEXBATOUT + chmod a+x $GENREFLEXBATOUT + result "done" + fi + + message "Writing $GENREFLEXROOTCINTSHOUT" + libdirreflex=$libdir + if test "x$haveconfig" = "x" ; then + libdirreflex='`dirname $0`/../lib' + fi + cat $GENREFLEXROOTCINTSHIN | sed -e "s|@libdir@|$libdirreflex|g" > $GENREFLEXROOTCINTSHOUT + chmod a+x $GENREFLEXROOTCINTSHOUT + result "done" + + if test "x$platform" = "xwin32"; then + message "Writing $GENREFLEXROOTCINTBATOUT" + if test "x$haveconfig" = "x" ; then + libdirreflex='%~d0%~p0\\..\\lib' + else + libdirreflex=`cygpath -m $libdir` + fi + cat $GENREFLEXROOTCINTBATIN | sed -e "s|@libdir@|$libdirreflex|g" > $GENREFLEXROOTCINTBATOUT + chmod a+x $GENREFLEXROOTCINTBATOUT + result "done" + fi +else + rm -f bin/genreflex* +fi + #--------------------------------------------------------------------- # config.status # @@ -7831,11 +7838,5 @@ if test "x$issue_explicitlink_warning" = "xyes"; then result "*** please remove them first using: rm -f lib/*.so." result "" fi -if [ "x$run_maintainer_clean" = "xyes" ]; then - result "*** Cleaning up previous non-C++11 build products, using:" - result "*** $gnumake maintainer-clean;$0 `cat config.status 2>/dev/null`" - $gnumake maintainer-clean - $0 `cat config.status 2>/dev/null` -fi exit 0 diff --git a/core/base/src/TPluginManager.cxx b/core/base/src/TPluginManager.cxx index c25b64a2ff65c..c8b0f8cdd4a3c 100644 --- a/core/base/src/TPluginManager.cxx +++ b/core/base/src/TPluginManager.cxx @@ -100,6 +100,7 @@ #include "TSystem.h" #include "TObjString.h" +#include TPluginManager *gPluginMgr; // main plugin manager created in TROOT @@ -398,7 +399,8 @@ void TPluginManager::LoadHandlersFromEnv(TEnv *env) TString ctor = strtok(0, ";\""); if (!ctor.Contains("(")) ctor = strtok(0, ";\""); - AddHandler(s, regexp, clss, plugin, ctor, "TEnv"); + std::cout << "class: " << clss << std::endl; + AddHandler(s, regexp, clss, plugin, ctor, "TEnv"); cnt++; } delete [] v; diff --git a/etc/plugins/ROOT@@Math@@Minimizer/P010_Minuit2Minimizer.C b/etc/plugins/ROOT@@Math@@Minimizer/P010_Minuit2Minimizer.C index 781b5f7e4c03f..2575db17ce019 100644 --- a/etc/plugins/ROOT@@Math@@Minimizer/P010_Minuit2Minimizer.C +++ b/etc/plugins/ROOT@@Math@@Minimizer/P010_Minuit2Minimizer.C @@ -1,5 +1,5 @@ void P010_Minuit2Minimizer() { - gPluginMgr->AddHandler("ROOT::Math::Minimizer", "Minuit2", "ROOT::Minuit2::Minuit2Minimizer", - "Minuit2", "Minuit2Minimizer(const char *)"); + gPluginMgr->AddHandler("ROOT::Math::Minimizer", "Minuit2", "ROOT::Minuit2::Minuit2Minimizer", + "Minuit2", "Minuit2Minimizer(const char *)"); } diff --git a/graf2d/asimage/src/libAfterImage/asfont.c b/graf2d/asimage/src/libAfterImage/asfont.c index 415bf6147686b..c069ddae2ab33 100644 --- a/graf2d/asimage/src/libAfterImage/asfont.c +++ b/graf2d/asimage/src/libAfterImage/asfont.c @@ -63,11 +63,11 @@ # include # include FT_FREETYPE_H # endif -# ifdef HAVE_FREETYPE_FREETYPE +/*# ifdef HAVE_FREETYPE_FREETYPE # include -# else +# else*/ # include -# endif +//# endif # if (FREETYPE_MAJOR == 2) && ((FREETYPE_MINOR == 0) || ((FREETYPE_MINOR == 1) && (FREETYPE_PATCH < 3))) # define FT_KERNING_DEFAULT ft_kerning_default # endif diff --git a/math/CMakeLists.txt b/math/CMakeLists.txt index 81838121a81ee..23f76b4fb9dea 100644 --- a/math/CMakeLists.txt +++ b/math/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(minuit) if(minuit2) add_subdirectory(minuit2) endif() +add_subdirectory(cmaes) add_subdirectory(fumili) add_subdirectory(physics) add_subdirectory(mlp) diff --git a/math/mathcore/src/Factory.cxx b/math/mathcore/src/Factory.cxx index 49d47646534e7..7827ca5d26b7b 100644 --- a/math/mathcore/src/Factory.cxx +++ b/math/mathcore/src/Factory.cxx @@ -26,6 +26,7 @@ // #define MATH_NO_PLUGIN_MANAGER // #define HAS_MINUIT // #define HAS_MINUIT2 +// #define HAS_CMAES #ifndef MATH_NO_PLUGIN_MANAGER // use ROOT Plug-in manager @@ -41,6 +42,9 @@ #ifdef HAS_MINUIT #include "TMinuitMinimizer.h" #endif +#ifdef HAS_CMAES +#include "TCMAESMinimizer.h" +#endif #ifdef R__HAS_MATHMORE #include "Math/GSLMinimizer.h" #include "Math/GSLNLSMinimizer.h" @@ -52,7 +56,7 @@ #include #include -//#define DEBUG +#define DEBUG #ifdef DEBUG #include #endif @@ -80,14 +84,21 @@ ROOT::Math::Minimizer * ROOT::Math::Factory::CreateMinimizer(const std::string & s1 = "Minuit"; minim = s1.c_str(); } + if (minimizerType == "cmaes") + { + s1 = "cmaes"; + minim = s1.c_str(); + } + std::cout << "minimizerType: " << minimizerType << " / minim: " << minim << std::endl; + if (minimizerType.empty() ) minim = ROOT::Math::MinimizerOptions::DefaultMinimizerType().c_str(); R__LOCKGUARD2(gROOTMutex); // create Minimizer using the PM TPluginHandler *h; - //gDebug = 3; + gDebug = 3; if ((h = gROOT->GetPluginManager()->FindHandler("ROOT::Math::Minimizer",minim ))) { if (h->LoadPlugin() == -1) { #ifdef DEBUG @@ -104,9 +115,10 @@ ROOT::Math::Minimizer * ROOT::Math::Factory::CreateMinimizer(const std::string & else std::cout << "Error creating Minimizer " << minimizerType << " " << algoType << std::endl; #endif - + std::cout << "min: " << min << std::endl; return min; } + std::cout << "returning 0\n"; return 0; } diff --git a/tutorials/fit/minuit2GausFit.C b/tutorials/fit/minuit2GausFit.C index 22385ce47a762..f5008c2e6b847 100644 --- a/tutorials/fit/minuit2GausFit.C +++ b/tutorials/fit/minuit2GausFit.C @@ -75,7 +75,7 @@ void minuit2GausFit() { int n = 1000; testGausFit("Minuit2",n); - testGausFit("Fumili2",n); + //testGausFit("Fumili2",n); } From 86fda1dccfc1f45f9bb0e83ae31e12498021c1de Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 6 May 2014 09:41:43 +0200 Subject: [PATCH 02/98] fixed configure for root 6 with cmaes --- configure | 657 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 339 insertions(+), 318 deletions(-) diff --git a/configure b/configure index d01bc73063acb..cface94748624 100755 --- a/configure +++ b/configure @@ -1,4 +1,4 @@ -#! /bin/sh +#!/bin/bash # # A (not so) simple configure script. # @@ -27,12 +27,17 @@ altcc= altcxx= altf77= altld= +altccset= +gcctoolchain= host= deprecated_options=" \ enable_mathcore \ enable_cern \ enable_editline \ + enable_cintex \ + enable_reflex \ + enable_cxx11 \ " options=" \ @@ -50,13 +55,10 @@ options=" \ enable_builtin_pcre \ enable_builtin_zlib \ enable_builtin_lzma \ - enable_cxx11 \ + enable_builtin_llvm \ enable_libcxx \ enable_castor \ enable_chirp \ - enable_cintex \ - enable_cling \ - enable_cmaes \ enable_cocoa \ enable_davix \ enable_dcache \ @@ -67,6 +69,7 @@ options=" \ enable_gviz \ enable_gdml \ enable_genvector \ + enable_geocad \ enable_gfal \ enable_glite \ enable_globus \ @@ -77,6 +80,7 @@ options=" \ enable_mathmore \ enable_memstat \ enable_minuit2 \ + enable_cmaes \ enable_monalisa \ enable_mysql \ enable_odbc \ @@ -88,7 +92,6 @@ options=" \ enable_python \ enable_qt \ enable_qtgsi \ - enable_reflex \ enable_roofit \ enable_ruby \ enable_rfio \ @@ -105,6 +108,7 @@ options=" \ enable_unuran \ enable_vc \ enable_vdt \ + enable_werror \ enable_winrtdebug \ enable_x11 \ enable_xft \ @@ -143,14 +147,13 @@ for c in $options $deprecated_options; do done for c in $options ; do eval ${c}_explicit="" ; done -enable_cxx11=no +enable_cxx11=yes enable_libcxx=no -enable_cling=no enable_cocoa= enable_afs=no enable_alloc=no -enable_cmaes=yes enable_gdml=no +enable_geocad=no enable_globus=no enable_explicitlink=no enable_gsl_shared=no @@ -158,6 +161,7 @@ enable_qt=no enable_qtgsi=no enable_roofit=no enable_minuit2=no +enable_cmaes=yes enable_rpath=no enable_ruby=no enable_shadowpw= @@ -166,6 +170,7 @@ enable_table=no enable_thread=yes # cannot be disabled (not in above options list) enable_unuran=no enable_vc=no +enable_werror=no enable_winrtdebug= enable_builtin_freetype=no enable_builtin_ftgl=no @@ -173,16 +178,18 @@ enable_builtin_glew=no enable_builtin_pcre=no enable_builtin_zlib=no enable_builtin_lzma=no +enable_builtin_llvm=yes enable_afdsmgrd=no if test "x$ENABLEALL" = "xyes"; then - enable_cmaes=yes enable_gdml=yes + enable_geocad=yes enable_qt=yes enable_qtgsi=yes enable_roofit=yes enable_minuit2=yes - enable_ruby=yes + enable_cmaes=yes + #enable_ruby=yes #not supported in ROOT v6.0.0 yet enable_table=yes enable_unuran=yes enable_vc=yes @@ -198,6 +205,9 @@ rm -f $logfile envvars=" THREAD \ ZLIB \ +LIBTIFF \ +LIBJPEG \ +LIBPNG \ LZMA \ OPENGL \ MYSQL \ @@ -236,7 +246,7 @@ MINUIT2 \ CMAES \ TABLE \ XMLDIR \ -ROOTDICTTYPE \ +CASROOT \ VC \ DAVIX \ " @@ -390,14 +400,14 @@ check_libcompat() { case $arch in macosx) - logmsg " lipo -info $chklibcompat | grep ' i386'" - if lipo -info $chklibcompat | grep ' i386' > /dev/null 2>& 1 ; then + logmsg " lipo $chklibcompat -verify_arch i386" + if lipo $chklibcompat -verify_arch i386 ; then ret=1 fi ;; macosx64) - logmsg " lipo -info $chklibcompat | grep ' x86_64'" - if lipo -info $chklibcompat | grep ' x86_64' > /dev/null 2>& 1 ; then + logmsg " lipo $chklibcompat -verify_arch x86_64" + if lipo $chklibcompat -verify_arch x86_64 ; then ret=1 fi ;; @@ -421,7 +431,7 @@ check_libcxxcompat() { # The result of the check is stored in is_libcxxcompat, 1 if true, # 0 otherwise, which should be immediately copied, since the variable # will be overwritten at next invocation of this function. - # To avoid this check, in case std types are not used in the public + # To skip this check, in case std types are not used in the public # API of the library, set skipchecklibcxxcompat="yes". is_libcxxcompat=1 @@ -1293,7 +1303,6 @@ check_explicit() fi } -#_____________________________________________________________________ invoke_preprocessor() { # This function will try to preprocess a given file. The result is stored in # preprocessor_output, which should be immediately copied, since the @@ -1336,7 +1345,6 @@ guess_architecture() { logmsg "rele=$rele" case "$arch:$chip:$rele" in aix*) arch=aix5 ;; - osf1*:alpha:*) arch=alphacxx6 ;; freebsd*:*:[789]*) arch=freebsd7 ;; freebsd*:*:6*) arch=freebsd5 ;; freebsd*:*:5*) arch=freebsd5 ;; @@ -1347,10 +1355,9 @@ guess_architecture() { hurd*:*:*) arch=hurddeb ;; linux:ia64:*) arch=linuxia64gcc ;; linux:x86_64:*) arch=linuxx8664gcc ;; - linux:alpha:*) arch=linuxalphagcc ;; + linux:x32:*) arch=linuxx32gcc ;; linux:arm*:*) arch=linuxarm ;; linux:hppa*:*) arch=linux ;; - linux:mips:*) arch=linuxmips ;; linux:sparc*:*) arch=linux ;; linux:parisc*:*) arch=linuxhppa ;; linux:ppc64*:*) arch=linuxppc64gcc ;; @@ -1361,7 +1368,6 @@ guess_architecture() { lynx:*:*) arch=lynxos ;; darwin:power*:*) arch=macosx ;; darwin:*86*:*) arch=macosx ;; - irix*:sgi*:*) arch=sgicc ;; sunos:sun*:6*) arch=solarisCC5 ;; sunos:sun*:5*) arch=solarisCC5 ;; sunos:sun*:4*) arch=solaris ;; @@ -1545,14 +1551,6 @@ THISROOTCSHIN=${ac_srcdir}/config/thisroot.csh THISROOTCSHOUT=bin/thisroot.csh THISROOTBATIN=${ac_srcdir}/config/thisroot.bat THISROOTBATOUT=bin/thisroot.bat -GENREFLEXSHIN=${ac_srcdir}/config/genreflex.in -GENREFLEXSHOUT=bin/genreflex -GENREFLEXBATIN=${ac_srcdir}/config/genreflex.bat.in -GENREFLEXBATOUT=bin/genreflex.bat -GENREFLEXROOTCINTSHIN=${ac_srcdir}/config/genreflex-rootcint.in -GENREFLEXROOTCINTSHOUT=bin/genreflex-rootcint -GENREFLEXROOTCINTBATIN=${ac_srcdir}/config/genreflex-rootcint.bat.in -GENREFLEXROOTCINTBATOUT=bin/genreflex-rootcint.bat SETXRDSHIN=${ac_srcdir}/config/setxrd.sh SETXRDSHOUT=bin/setxrd.sh SETXRDCSHIN=${ac_srcdir}/config/setxrd.csh @@ -1582,7 +1580,6 @@ FIRST argument one of the architecures given at the end of this message. --bindir Binary installation dir (/bin) --build Build configuration [debug, ...], overrides the ROOTBUILD shell variable - --cintincdir CINT interpeted headers (/cint) --datadir Data installation dir (/share/root) --docdir Documentation (/share/doc/root) --elispdir Where to put Emacs Lisp (/share/emacs/site-lisp) @@ -1599,11 +1596,22 @@ FIRST argument one of the architecures given at the end of this message. --testdir Tests (/test) --tutdir Tutorials (/tutorial) -If any of the flags --cintincdir, --datadir, --docdir, --etcdir, --iconpath +If any of the flags --datadir, --docdir, --etcdir, --iconpath --incdir, --libdir, --macrodir, --mandir, or --prefix is given, ROOT will be compiled with static directory names, and you should not set the ROOTSYS environment variable. +To reduce the output of configure by removing the trailing howto message, use: + + --nohowto + +Use the flag: + + --fail-on-missing + +to force configure to fail if a component that has been explicitly enabled +is missing some dependencies and can not be built. + enable/disable options, prefix with either --enable- or --disable- afdsmgrd Dataset manager for PROOF-based analysis facilities @@ -1612,20 +1620,16 @@ enable/disable options, prefix with either --enable- or --disable- asimage Image processing support, requires libAfterImage astiff Include tiff support in image processing bonjour Bonjour support, requires libdns_sd and/or Avahi - builtin-afterimage Built included libAfterImage, or use system libAfterImage - builtin-ftgl Built included libFTGL, or use system libftgl - builtin-freetype Built included libfreetype, or use system libfreetype - builtin-glew Built included libGLEW, or use system libGLEW - builtin-pcre Built included libpcre, or use system libpcre - builtin-zlib Built included libz, or use system libz - builtin-lzma Built included liblzma, or use system liblzma - cxx11 Build using C++11 compatible mode, requires gcc > 4.7.x or clang - libcxx Build using libc++, required by clang cxx11 option (MacOS X only, for the time being) + builtin-afterimage Build included libAfterImage, or use system libAfterImage + builtin-ftgl Build included libFTGL, or use system libftgl + builtin-freetype Build included libfreetype, or use system libfreetype + builtin-glew Build included libGLEW, or use system libGLEW + builtin-pcre Build included libpcre, or use system libpcre + builtin-zlib Build included libz, or use system libz + builtin-lzma Build included liblzma, or use system liblzma + libcxx Build using libc++, required by clang option (MacOS X only, for the time being) castor CASTOR support, requires libshift from CASTOR >= 1.5.2 chirp Chirp filesystem support, requires cctools >= 3.2.2 - cintex Build the libCintex Reflex interface library - cling Use cling as interpreter backend (experimental!), needs --with-llvm-config - cmaes Build the wrapper to the libcmaes mininmizer library cocoa Use native Cocoa/Quartz graphics backend (MacOS X only) davix DavIx library for HTTP/WEBDAV access dcache dCache support, requires libdcap from DESY @@ -1635,6 +1639,7 @@ enable/disable options, prefix with either --enable- or --disable- fitsio Read images and data from FITS files, requires cfitsio gviz Graphs visualization support, requires graphviz gdml GDML writer and reader + geocad ROOT-CAD Interface gfal GFAL support, requires libgfal globus Globus authentication support, requires Globus toolkit glite gLite support, requires libglite-api-wrapper v.3 from GSI (https://subversion.gsi.de/trac/dgrid/wiki) @@ -1643,9 +1648,10 @@ enable/disable options, prefix with either --enable- or --disable- krb5 Kerberos5 support, requires Kerberos libs ldap LDAP support, requires (Open)LDAP libs genvector Build the new libGenVector library - mathmore Build the new libMathMore extended math library, requires GSL (vers. >= 1.8) + mathmore Build the new libMathMore extended math library, requires GSL (vers. >= 1.10) memstat A memory statistics utility, helps to detect memory leaks minuit2 Build the new libMinuit2 minimizer library + cmaes Build the wrapper to the libcmaes mininmizer library monalisa Monalisa monitoring support, requires libapmoncpp mysql MySQL support, requires libmysqlclient odbc ODBC support, requires libiodbc or libodbc @@ -1654,10 +1660,9 @@ enable/disable options, prefix with either --enable- or --disable- pgsql PostgreSQL support, requires libpq pythia6 Pythia6 EG support, requires libPythia6 pythia8 Pythia8 EG support, requires libPythia8 >= 8180 - python Python ROOT bindings, requires python >= 2.2 - qt Qt graphics backend, requires libqt >= 4.x - qtgsi GSI's Qt integration, requires libqt >= 3 - reflex Build the libReflex dictionary library + python Python ROOT bindings, requires python >= 2.5 + qt Qt graphics backend, requires libqt >= 4.8 + qtgsi GSI's Qt integration, requires libqt >= 4.8 rfio RFIO support, requires libshift from CASTOR >= 1.5.2 roofit Build the libRooFit advanced fitting package rpath Set run-time library load path on executables @@ -1671,8 +1676,9 @@ enable/disable options, prefix with either --enable- or --disable- ssl SSL encryption support, requires openssl table Build libTable contrib library tmva Build TMVA multi variate analysis library - vc Vc adds a few new types for portable and intuitive SIMD programming unuran UNURAN - package for generating non-uniform random numbers + vc Vc adds a few new types for portable and intuitive SIMD programming + werror Turn on -Werror on most systems to force warnings to be errors winrtdebug Link against the Windows debug runtime library x11 X11 support xml XML parser interface @@ -1709,7 +1715,6 @@ with options, prefix with --with-, enables corresponding support davix-libdir DavIx support, location of libdavix dcap-incdir dCache support, location of dcap.h dcap-libdir dCache support, location of libdcap - dicttype dictionary type: "cint" (default), "reflex", or "gccxml" dnssd-libdir Bonjour support, location of libdns_sd dnssd-incdir Bonjour support, location of dns_sd.h finkdir Prefix of extra MacOS X package manager (Fink, MacPorts, ...) @@ -1749,6 +1754,8 @@ with options, prefix with --with-, enables corresponding support monalisa-libdir Monalisa support, location of libapmoncpp mysql-incdir MySQL support, location of mysql.h mysql-libdir MySQL support, location of libmysqlclient + occ-incdir GEOCAD support, location of OpenCascade inc files + occ-libdir GEOCAD support, location of OpenCascade lib files odbc-incdir ODBC support, location of sqlext.h odbc-libdir ODBC support, location of libiodbc or libodbc opengl-incdir OpenGL support, location of GL/gl.h @@ -1797,6 +1804,8 @@ with compiler options, prefix with --with-, overrides default value cxx alternative C++ compiler and options to be used f77 alternative Fortran compiler and options to be used ld alternative Linker and options to be used + gcc-toolchain directory where gcc is installed (needed for compilation + of clang/LLVM in case not the default gcc is used) clang use clang compiler instead of gcc (mutual exclusive with the cc, cxx and ld options) @@ -1873,18 +1882,13 @@ fi platform=`grep "^PLATFORM *=" ${ac_srcdir}/config/Makefile.$arch | awk '{ print $3 }'` case $arch in -sgicc) - logmsg "Will check 32bit libraries" - checklib32="yes" ;; -linuxppc64*|sgicc64) +linuxppc64*) logmsg "Will ONLY check 64bit libraries" checkonlylib64="yes" ;; linuxx8664k1om*) logmsg "Will not check 64bit libraries" checklinux64="no" checklib64="no" - enable_cintex="no" - enable_reflex="no" enable_genvector="no" enable_tmva="no" ;; @@ -1892,6 +1896,9 @@ linuxx8664*) logmsg "Will check 64bit libraries" checklinux64="yes" checklib64="yes" ;; +linuxx32*) + logmsg "Will check x32 libraries in the future" + logmsg "For now expect proper libraries through configure flags" ;; hpuxia64acc) logmsg "Will check HP/UX 64bit libraries" checkhpux64="yes" ;; @@ -1923,7 +1930,7 @@ ios*) ios7=yes fi xcodepath=`/usr/bin/xcode-select -print-path` - if test "x$arch" = "xios"; then + if test "x$arch" = "xios" || test "x$arch" = "xios64"; then iossdk=$xcodepath/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$iosvers.sdk else iossdk=$xcodepath/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$iosvers.sdk @@ -1938,10 +1945,9 @@ ios*) # make available to conftest.mk scripts export IOSSDK=$iossdk export IOSVERS=$iosvers - enable_cintex="no" - enable_reflex="no" enable_genvector="no" enable_tmva="no" + enable_vdt="no" ;; win32) logmsg "Will use by default builtin versions of libraries on Win32" @@ -1982,6 +1988,9 @@ if test "x$platform" = "xmacosx" ; then if [ `sw_vers | sed -n 's/ProductVersion://p' | cut -d . -f 2` -ge 6 ]; then macosx106=yes fi + if [ `sw_vers | sed -n 's/ProductVersion://p' | cut -d . -f 2` -ge 7 ]; then + macosx107=yes + fi if [ `sw_vers | sed -n 's/ProductVersion://p' | cut -d . -f 2` -ge 8 ]; then macosx108=yes fi @@ -2076,15 +2085,11 @@ if test $# -gt 0 ; then --with-cern-libdir=*) echo "WARNING: option $1 is deprecated and ignored"'!' ;; --with-chirp-incdir=*) chirpincdir=$optarg ; enable_chirp="yes" ;; --with-chirp-libdir=*) chirplibdir=$optarg ; enable_chirp="yes" ;; - --with-cint-maxstruct=*) cintmaxstruct=$optarg ;; - --with-cint-maxtypedef=*) cintmaxtypedef=$optarg;; - --with-cint-longline=*) cintlongline=$optarg ;; --with-cppunit=*) cppunit=$optarg ;; --with-davix-incdir=*) davixincdir=$optarg ; enable_davix="yes" ;; --with-davix-libdir=*) davixlibdir=$optarg ; enable_davix="yes" ;; --with-dcap-incdir=*) dcapincdir=$optarg ; enable_dcache="yes" ;; --with-dcap-libdir=*) dcaplibdir=$optarg ; enable_dcache="yes" ;; - --with-dicttype=*) dicttype=$optarg ;; --with-dnssd-incdir=*) dnssdincdir=$optarg ; enable_bonjour="yes" ;; --with-dnssd-libdir=*) dnssdlibdir=$optarg ; enable_bonjour="yes" ;; --with-avahi-incdir=*) avahiincdir=$optarg ; enable_bonjour="yes" ;; @@ -2107,8 +2112,11 @@ if test $# -gt 0 ; then --with-gsl-incdir=*) gslincdir=$optarg ; enable_gsl="yes" ;; --with-gsl-libdir=*) gsllibdir=$optarg ; enable_gsl="yes" ;; --with-globus=*) globusdir=$optarg ; enable_globus="yes" ;; - --with-globus-incdir=*) globusincdir=$optarg ; enable_globus="yes" ;; - --with-globus-libdir=*) globuslibdir=$optarg ; enable_globus="yes" ;; + --with-globus-incdir=*) globusincdir=$optarg ; enable_globus="yes" ;; + --with-globus-libdir=*) globuslibdir=$optarg ; enable_globus="yes" ;; + --with-geocad=*) geocaddir=$optarg ; enable_geocad="yes" ;; + --with-occ-incdir=*) occincdir=$optarg ; enable_geocad="yes" ;; + --with-occ-libdir=*) occlibdir=$optarg ; enable_geocad="yes" ;; --with-gccxml=*) gccxml=$optarg ;; --with-hdfs-incdir=*) hdfsincdir=$optarg ; enable_hdfs="yes" ;; --with-hdfs-libdir=*) hdfslibdir=$optarg ; enable_hdfs="yes" ;; @@ -2120,7 +2128,7 @@ if test $# -gt 0 ; then --with-krb5-libdir=*) krb5libdir=$optarg ; enable_krb5="yes" ;; --with-ldap-incdir=*) ldapincdir=$optarg ; enable_ldap="yes" ;; --with-ldap-libdir=*) ldaplibdir=$optarg ; enable_ldap="yes" ;; - --with-llvm-config=*) llvmconfig=$optarg ;; # require explicit --enable-cling + --with-llvm-config=*) llvmconfig=$optarg ; enable_builtin_llvm=no;; --with-macosxvers=*) macosxvers=$optarg ;; --with-mysql-incdir=*) mysqlincdir=$optarg ; enable_mysql="yes" ;; --with-mysql-libdir=*) mysqllibdir=$optarg ; enable_mysql="yes" ;; @@ -2168,10 +2176,11 @@ if test $# -gt 0 ; then --with-xrootd=*) xrootddir=$optarg ; enable_xrootd="yes" ;; --with-xrootd-incdir=*) xrdincdir=$optarg ; enable_xrootd="yes" ;; --with-xrootd-libdir=*) xrdlibdir=$optarg ; enable_xrootd="yes" ;; - --with-cc=*) altcc=$optarg ;; + --with-cc=*) altcc=$optarg ; altccset=1 ;; --with-cxx=*) altcxx=$optarg ;; --with-f77=*) altf77=$optarg ;; --with-ld=*) altld=$optarg ;; + --with-gcc-toolchain=*) gcctoolchain=$optarg ;; --with-clang) altcc=clang; altcxx=clang++; altld=clang++ ;; --with-hostcc=*) hostcc=$optarg ;; --with-hostcxx=*) hostcxx=$optarg ;; @@ -2185,26 +2194,27 @@ if test $# -gt 0 ; then f=`echo $1 | sed -e 's/--//' -e 's/-/_/g' -e 's/++11/xx11/'` eval prev='$'`echo ${f}` eval prev_expl='$'`echo ${f}_explicit` - if test "${prev}:${prev_expl}" = "yes:"; then - echo "INFO: $1: already enabled by default." - fi if test ! "x`echo ${deprecated_options} | grep ${f}`" = "x"; then echo "WARNING: option $1 is deprecated and ignored"'!' + else + if test "${prev}:${prev_expl}" = "yes:"; then + echo "INFO: $1: already enabled by default." + fi + if test "x${prev_expl}" = "xno"; then + echo "WARNING: conflicting --disable / $1, $1 wins" + fi + eval ${f}=yes + eval ${f}_explicit=yes fi - if test "x${prev_expl}" = "xno"; then - echo "WARNING: conflicting --disable / $1, $1 wins" - fi - eval ${f}=yes - eval ${f}_explicit=yes for c in $options ; do if test "x$c" = "x$f" ; then f="" - fi + fi done for c in $deprecated_options ; do if test "x$c" = "x$f" ; then f="" - fi + fi done if test "x$f" != "x" ; then echo "Invalid option '$1'. Try $0 --help" ; exit 1 ; @@ -2214,19 +2224,28 @@ if test $# -gt 0 ; then f=`echo $1 | sed -e 's/--disable/enable/' -e 's/-/_/g' -e 's/++11/xx11/'` eval prev='$'`echo ${f}` eval prev_expl='$'`echo ${f}_explicit` - if test "${prev}:${prev_expl}" = "xno:"; then - echo "INFO: $1: already disabled by default." - fi - if test "x${prev_expl}" = "xyes"; then - echo "WARNING: conflicting --enable / $1, $1 wins" + if test ! "x`echo ${deprecated_options} | grep ${f}`" = "x"; then + echo "WARNING: option $1 is deprecated and ignored"'!' + else + if test "${prev}:${prev_expl}" = "xno:"; then + echo "INFO: $1: already disabled by default." + fi + if test "x${prev_expl}" = "xyes"; then + echo "WARNING: conflicting --enable / $1, $1 wins" + fi + eval ${f}=no + eval ${f}_explicit=no fi - eval ${f}=no - eval ${f}_explicit=no for c in $options ; do if test "x$c" = "x$f" ; then f="" fi done + for c in $deprecated_options ; do + if test "x$c" = "x$f" ; then + f="" + fi + done if test "x$f" != "x" ; then echo "Invalid option '$1'. Try $0 --help" ; exit 1 ; fi @@ -2242,7 +2261,6 @@ if test $# -gt 0 ; then # --aclocaldir=*) haveconfig=-DR__HAVE_CONFIG ; aclocaldir=$optarg ;; --bindir=*) haveconfig=-DR__HAVE_CONFIG ; bindir=$optarg ;; - --cintincdir=*) haveconfig=-DR__HAVE_CONFIG ; cintincdir=$optarg ;; --datadir=*) haveconfig=-DR__HAVE_CONFIG ; datadir=$optarg ;; --docdir=*) haveconfig=-DR__HAVE_CONFIG ; docdir=$optarg ;; --elispdir=*) haveconfig=-DR__HAVE_CONFIG ; elispdir=$optarg ;; @@ -2451,6 +2469,15 @@ if test $found_comp -eq 0 ; then altf77= fi +# the path for the gcctoolchain in case not the system gcc is used to +# build clang/LLVM. This path is used to build clang/LLVM. +if test "x$gcctoolchain" != "x"; then + if test "x$altccset" = "x" ; then + result "`basename $0`: no alternative gcc compiler specified, incompatible with --with-gcc-toolchain option" + exit 1 + fi +fi + ###################################################################### # ### echo %%% Check host environment in case of cross compiling @@ -2508,17 +2535,17 @@ if test "x$enable_cxx11" = "xyes"; then check_cxxopt -std=c++11 if test $cxxopt_result -eq 0 ; then enable_cxx11="no" - result "no" + result "no" result "`basename $0`: c++11 mode is requested but the current compiler does not support it." exit 1 else - usecxx11="define" + usecxx11="define" # on OS X libcxx is required for C++11 support with clang # so turn the option on when using clang if test "x$platform" = "xmacosx" && echo $altcxx | grep 'clang++' > /dev/null 2>&1; then enable_libcxx="yes" fi - result "yes" + result "yes" fi fi @@ -2550,6 +2577,69 @@ if test "x$enable_libcxx" = "xyes" ; then fi fi +###################################################################### +# +### echo %%% Check for linker's support of --no-ctors-in-init-array +# +### This changes the sequence for static initialization to be right +### to left. +# +logmsg "Derminining support for --no-ctors-in-init-array" +cat < conftest.mk +include ${ac_srcdir}/config/Makefile.${arch} +CC = ${altcc} +CXX = ${altcxx} +LD = ${altld} +conftest: conftest.cxx + \$(CC) \$(LDFLAGS) -Wl,--no-ctors-in-init-array \$^ -o \$@ + +conftest.cxx: + echo 'int main(int,char*[]){return 0;}' >> \$@ +EOF +$gnumake -f conftest.mk >> $logfile 2>&1 +if test $? -eq 0 ; then + logmsg " supported" + ctorsinitarray="yes" +else + logmsg " not supported" + ctorsinitarray="no" +fi +rm -f conftest.mk conftest conftest.cxx + +###################################################################### +# +### echo %%% Check for builtin or external LLVM/Clang +# +hasllvm="undef" +llvmdir="/**/" +if test "x$enable_builtin_llvm" = "x" || \ + test "x$enable_builtin_llvm" = "xno" ; then + message "Checking for llvm-config for external llvm" + # allow LLVMDIR instead of --with-llvm-config + if test "x$llvmconfig" = "x" ; then + if test ! "x$LLVMDIR" = "x" ; then + llvmconfig="$LLVMDIR/bin" + fi + fi + if test ! "x$llvmconfig" = "x"; then + if test -d "$llvmconfig"; then + llvmconfig=$llvmconfig/llvm-config + fi + if test -f $llvmconfig && test -x $llvmconfig; then + hasllvm="define" + llvmdir="`dirname $llvmconfig`" + llvmdir='"'"`dirname $llvmdir`"'"' + fi + fi + if test "x$hasllvm" = "xundef"; then + enable_builtin_llvm="yes" + llvmconfig="" + result "no (needs --with-llvm-config or \$LLVMDIR)" + else + result "$llvmconfig" + fi +fi + ###################################################################### # ### echo %%% Check if native MacOS X Cocoa/Quartz backend should be build @@ -2557,7 +2647,7 @@ fi if test ! "x$platform" = "xmacosx"; then enable_cocoa="no" fi -if test "x$macosx108" = "xyes" && test "x$enable_cocoa" = "x"; then +if test "x$macosx107" = "xyes" && test "x$enable_cocoa" = "x"; then enable_cocoa="yes" fi if test "x$enable_cocoa" = "x"; then @@ -3008,8 +3098,8 @@ if test ! "x$enable_opengl" = "xno" && test ! "x$platform" = "xwin32" ; then opengllibdir=$found_dir if test ! "x$macosx105" = "x" && test "x$macosx106" = "x" ; then - # Mac OS X 10.5 problem - opengllib="-dylib_file /usr/X11R6/lib/libGL.dylib:/usr/X11R6/lib/libGL.dylib -lGL" + # Mac OS X 10.5 problem + opengllib="-dylib_file /usr/X11R6/lib/libGL.dylib:/usr/X11R6/lib/libGL.dylib -lGL" fi skipchecklibcxxcompat="yes" @@ -3253,7 +3343,7 @@ if test ! "x$enable_oracle" = "xno"; then $ORACLE ${ORACLE:+$ORACLE/lib} $ORACLELIBDIR \ /usr/local/lib /usr/lib /usr/lib/oracle/*/client/lib if test "x$found_lib" = "x"; then - oraclelib="" + oraclelib="" elif test ! "x$oraclelib" = "x"; then oraclelib="$oraclelib $found_lib" fi @@ -3325,8 +3415,8 @@ if test ! "x$enable_sqlite" = "xno"; then /usr/include /usr/local/include \ /usr/include/sqlite /usr/local/include/sqlite /usr/local/sqlite/include \ /usr/include/sqlite3 /usr/local/include/sqlite3 /usr/local/sqlite3/include \ - /usr/sqlite /opt/sqlite /opt/sqlite3/include \ - /usr/sqlite3 /opt/sqlite3 /opt/sqlite/include + /usr/sqlite /opt/sqlite /opt/sqlite3/include \ + /usr/sqlite3 /opt/sqlite3 /opt/sqlite/include sqliteinc=$found_hdr sqliteincdir=$found_dir @@ -3497,7 +3587,7 @@ if test ! "x$enable_qt" = "xno" || \ qtincdir="$qtincdir $i" fi done - qtverneed="4.3.0" + qtverneed="4.8.0" qttoonew="5.0.0" qttestdir=$qtmainincdir/../src/corelib/global if test ! -d $qttestdir ; then @@ -3591,7 +3681,7 @@ if test ! "x$enable_rfio" = "xno" ; then $RFIO ${RFIO:+$RFIO/include} \ ${RFIO:+$RFIO/include/shift} ${RFIO:+$RFIO/h} \ /cern/pro/include /cern/new/include /cern/old/include \ - /opt/shift/include /usr/local/shift/include /usr/include/shift \ + /opt/shift/include /usr/local/shift/inlcude /usr/include/shift \ /usr/local/include/shift /usr/include /usr/local/include shiftinc=$found_hdr shiftincdir=$found_dir @@ -3666,7 +3756,7 @@ if test ! "x$enable_castor" = "xno" ; then $CASTOR ${CASTOR:+$CASTOR/include} \ ${CASTOR:+$CASTOR/include/shift} ${CASTOR:+$CASTOR/h} \ /cern/pro/include /cern/new/include /cern/old/include \ - /opt/shift/include /usr/local/shift/include /usr/include/shift \ + /opt/shift/include /usr/local/shift/inlcude /usr/include/shift \ /usr/local/include/shift /usr/include /usr/local/include castorinc=$found_hdr castorincdir=$found_dir @@ -3688,7 +3778,7 @@ if test ! "x$enable_castor" = "xno" ; then $CASTOR ${CASTOR:+$CASTOR/include} \ ${CASTOR:+$CASTOR/include/shift} ${CASTOR:+$CASTOR/h} \ /cern/pro/include /cern/new/include /cern/old/include \ - /opt/shift/include /usr/local/shift/include /usr/include/shift \ + /opt/shift/include /usr/local/shift/inlcude /usr/include/shift \ /usr/local/include/shift /usr/include /usr/local/include stagerinc=$found_hdr @@ -4444,13 +4534,17 @@ if test ! "x$enable_asimage" = "xno" ; then fi # If we didn't find the system libAfterImage, or the user didn't ask # for a system library, then see if we have various headers needed. + # For Cocoa backend force libAfterImage builtin jpeg and png libs + # to avoid system versions based on X11. if test "x$enable_builtin_afterimage" = "xyes" && test ! "x$enable_cocoa" = "xyes"; then check_header "jpeglib.h" "" \ + ${LIBJPEG:+$LIBJPEG/include} \ $ASIMAGE ${ASIMAGE:+$ASIMAGE/include} \ ${finkdir:+$finkdir/include} \ /usr/local/include /usr/include /opt/include asjpegincdir=$found_dir check_header "png.h" "" \ + ${LIBPNG:+$LIBPNG/include} \ $ASIMAGE ${ASIMAGE:+$ASIMAGE/include} \ ${ASPNG:+$ASPNG/include} \ ${finkdir:+$finkdir/include} \ @@ -4459,6 +4553,7 @@ if test ! "x$enable_asimage" = "xno" ; then aspngincdir=$found_dir if test ! "x$enable_astiff" = "xno" ; then check_header "tiffio.h" "" \ + ${LIBTIFF:+$LIBTIFF/include} \ $ASIMAGE ${ASIMAGE:+$ASIMAGE/include} \ ${finkdir:+$finkdir/include} \ /usr/local/include /usr/include /opt/include @@ -4480,6 +4575,8 @@ if test ! "x$enable_asimage" = "xno" ; then fi for k in $aslibs ; do check_library $k "$enable_shared" "" \ + ${LIBJPEG:+$LIBJPEG/lib} ${LIBPNG:+$LIBPNG/lib} \ + ${LIBTIFF:+$LIBTIFF/lib} ${ZLIB:+$ZLIB/lib} \ $ASIMAGE ${ASIMAGE:+$ASIMAGE/lib} ${ASPNG:+$ASPNG/lib} \ ${finkdir:+$finkdir/lib} \ /usr/local/lib /usr/X11/lib /usr/lib /opt/lib @@ -4516,6 +4613,39 @@ fi check_explicit "$enable_asimage" "$enable_asimage_explicit" \ "Explicitly required AfterImage dependencies not fulfilled" +###################################################################### +# +### echo %%% GEOCAD Library - Contributed library +# +# (See http://www.opencascade.org/) +# +# If the user has set the flags "--disable-geocad", we don't check for +# OpenCascade at all. +# +if test ! "x$enable_geocad" = "xno"; then + # Check for OpenCascade include and library + check_header "XCAFApp_Application.hxx" "$occincdir" \ + $CASROOT ${CASROOT:+$CASROOT/inc} /usr/include/opencascade \ + /usr/include + occinc=$found_hdr + occincdir=$found_dir + + check_library "libTKXCAF" "$enable_shared" "$occlibdir" \ + $CASROOT ${CASROOT:+$CASROOT/lib} /usr/lib + occlib=$found_lib + occlibdir=$found_dir + + if test ! "x$occlib" = "x" ; then + occlib="-lTKPrim -lTKBRep -lTKOffset -lTKGeomBase -lTKShHealing -lTKTopAlgo -lTKSTEP -lTKG2d -lTKBool -lTKBO -lTKXCAF -lTKXDESTEP -lTKLCAF -lTKernel -lTKXSBase -lTKG3d -lTKMath" + fi + + if test "x$occincdir" = "x" || test "x$occlib" = "x"; then + enable_geocad="no" + fi +fi +check_explicit "$enable_geocad" "$enable_geocad_explicit" \ + "Explicitly required GeoCad dependencies not fulfilled" + ###################################################################### # ### echo %%% LDAP Support - Third party libraries @@ -4571,6 +4701,11 @@ check_explicit "$enable_ldap" "$enable_ldap_explicit" \ # # (See http://www.python.org) # +if test ! "x$enable_python" = "xno" ; then + # PyROOT depends on cling + message "Checking for PyROOT prerequisites" + result "yes" +fi if test ! "x$enable_python" = "xno" ; then # Check for Python include and library mypython=`$cwhich python 2> /dev/null` @@ -4899,7 +5034,7 @@ if test "x$enable_xrootd" = "xyes" ; then fi if test "x$oldver" = "xyes" ; then decver=`echo $tmpver | sed 's|[^0-9]||g' | cut -c1-8` - fi + fi fi fi # Protect against 3.3.0, first version with 'include/xrootd/private' @@ -5970,16 +6105,6 @@ fi check_explicit "$enable_krb5" "$enable_krb5_explicit" \ "Explicitly required Kerberos5 dependencies not fulfilled" -###################################################################### -# -### echo %%% libcmaes support - Third party libraries -check_header "cmaes.h" "/home/beniz/research/siminole/dev/libcmaes/src" /usr/include -cmaesinc=$found_hdr -cmaesincdir=$found_dir -check_library "libcmaes" "yes" "/home/beniz/research/siminole/dev/libcmaes/src/.libs" /usr/lib -cmaeslib=$found_lib -cmaeslibdir=$found_dir - ###################################################################### # ### echo %%% Communication of errors library @@ -6199,7 +6324,6 @@ sed -e "s|@avxcxxflag@|$avxcxxflag|" \ < Makefile.tmp > Makefile.tmpp mv Makefile.tmpp Makefile.tmp - ###################################################################### # ### echo %%% MathMore Library - Contributed library @@ -6218,11 +6342,11 @@ if test ! "x$enable_mathmore" = "xno"; then ${finkdir:+$finkdir/include} \ /usr/local/include /usr/include /opt/gsl/include - # check for gsl version >= 1.8 + # check for gsl version >= 1.10 if test ! "x$found_dir" = "x"; then - message "Checking for GSL version >= 1.8" - gsl_version=`grep "define GSL" $found_dir/gsl/gsl_version.h | sed 's/^.*"\([0-9]\..*[0-9]\)"/\1/' | awk 'BEGIN { FS="." } { printf "%d", $1 * 1000 + $2 }'` - if test $gsl_version -lt 1008; then + message "Checking for GSL version >= 1.10" + gsl_version=`grep "define GSL_VERSION" $found_dir/gsl/gsl_version.h | sed 's/^.*"\([0-9]\..*[0-9]\)"/\1/' | awk 'BEGIN { FS="." } { printf "%d", $1 * 1000 + $2 }'` + if test $gsl_version -lt 1010; then gslskip="skip" result "no" enable_mathmore="no" @@ -6385,49 +6509,6 @@ fi check_explicit "$enable_genvector" "$enable_genvector_explicit" \ "Explicitly required GenVector dependencies not fulfilled" -###################################################################### -# -### echo %%% Cintex Library - Contributed library -# -message "Checking whether to build libCintex" -if test ! "x$enable_cintex" = "xno"; then - # only enable on i386, i686, x86_64: - case "$chip" in - i*86 | x86_64) - enable_cintex="yes" - result "yes" - ;; - *) - case `uname -m` in - i*86 | x86_64) - enable_cintex="yes" - result "yes" - ;; - *) - logmsg " incompatible Cintex architecture $chip" - enable_cintex="" - result "no" - ;; - esac - esac -else - enable_cintex="" - result "no" -fi - -###################################################################### -# -### echo %%% Reflex Library - Contributed library -# -message "Checking whether to build libReflex" -if test ! "x$enable_reflex" = "xno"; then - enable_reflex="yes" - result "yes" -else - enable_reflex="" - result "no" -fi - ###################################################################### # ### echo %%% RooFit Library - Contributed library @@ -6456,16 +6537,14 @@ fi ###################################################################### # -### echo %%% CMAES Library - Contributed library +### echo %%% libcmaes support - Third party libraries # -message "Checking whether to build libcmaes" -if test "x$enable_cmaes" = "xyes" || test ! "x$CMAES" = "x"; then - enable_cmaes="yes" - result "yes" -else - enable_cmaes="" - result "no" -fi +check_header "cmaes.h" "/home/beniz/research/siminole/dev/libcmaes/src" /usr/include +cmaesinc=$found_hdr +cmaesincdir=$found_dir +check_library "libcmaes" "yes" "/home/beniz/research/siminole/dev/libcmaes/src/.libs" /usr/lib +cmaeslib=$found_lib +cmaeslibdir=$found_dir ###################################################################### # @@ -6494,7 +6573,6 @@ else result "no" hasvc="undef" fi - ###################################################################### # ### echo %%% VDT Library - Contributed library @@ -6510,7 +6588,6 @@ else hasvdt="undef" fi - ###################################################################### # ### echo %%% GDML Library - Contributed library @@ -6607,78 +6684,6 @@ else fi result "$enable_afdsmgrd$afdsmgrdapmonmsg" -###################################################################### -# -### echo %%% Cling - LLVM/clang based interpreter prototype -# -message "Checking whether to integrate experimental cling" -hascling="undef" -clingextrares="" -if test ! "x$enable_cling" = "xno"; then - # allow LLVMDIR instead of --with-llvm-config - if test "x$llvmconfig" = "x" ; then - if test ! "x$LLVMDIR" = "x" ; then - llvmconfig="$LLVMDIR/bin" - else - clingextrares="(needs --with-llvm-config or \$LLVMDIR)" - fi - result "no" - fi - if test ! "x$llvmconfig" = "x"; then - if test -d "$llvmconfig"; then - llvmconfig=$llvmconfig/llvm-config - fi - if test -f $llvmconfig && test -x $llvmconfig; then - hascling="define" - fi - fi -fi -if test "x$hascling" = "xundef"; then - enable_cling="no" - result "no $clingextrares" -else - enable_cling="yes" - result "yes" -fi - -###################################################################### -# -### echo %%% What dictionaries to build -# -# Can be either CINT (default), reflex, or gccxml. -# Option will be passed to rootcint(_tmp), -# and root-config --libs will have -lReflex if needed. -# -message "Checking what type of dictionaries to build" -# --with-dicttype overrides env var ROOTDICTTYPE -if test "x$dicttype" = "x" ; then - dicttype="$ROOTDICTTYPE" -fi - -# set default to CINT -if test "x$dicttype" = "x"; then - dicttype=cint -fi - -case "$dicttype" in - cint);; - reflex | gccxml) - # check that cintex is enabled for reflex/gccxml - if test ! "x$enable_cintex" = "xyes"; then - result "Cannot generate $dicttype dictionaries with cintex disabled." - dicttype=cint - fi ;; - *) - result "Unknown dictionary \"$dicttype\"." - result " Must be one of cint, reflex, gccxml." - dicttype=cint - ROOTDICTTYPE="trigger print info" - ;; -esac - -# Print info if dicttype!=cint, or --with-dict overrides $ROOTDICTTYPE -result "$dicttype" - ###################################################################### # ### echo %%% Debian or Red Hat package list @@ -6701,6 +6706,7 @@ if test "x$show_pkglist" = "xyes" ; then test "x$enable_roofit" = "xyes" && pl="$pl libroot-roofit" test "x$enable_asimage" = "xyes" && pl="$pl root-plugin-graf2d-asimage" test "x$enable_gdml" = "xyes" && pl="$pl root-plugin-geom-gdml" + test "x$enable_geocad" = "xyes" && pl="$pl root-plugin-geom-geocad" test "x$enable_qt" = "xyes" && pl="$pl root-plugin-gui-qt root-plugin-graf2d-qt" test "x$enable_castor" = "xyes" && pl="$pl root-plugin-io-castor" test "x$enable_chirp" = "xyes" && pl="$pl root-plugin-io-chirp" @@ -6713,7 +6719,7 @@ if test "x$show_pkglist" = "xyes" ; then test "x$enable_fitsio" = "xyes" && pl="$pl root-plugin-graf2d-fitsio" test "x$enable_gviz" = "xyes" && pl="$pl root-plugin-graf2d-gviz" test "x$enable_minuit2" = "xyes" && pl="$pl root-plugin-math-minuit2" - test "x$enable_cmaes" = "xyes" && pl="$pl root-plugin-math-cmaes" + test "x$enable_cmaes" = "xyes" && pl="$pl root-plugin-math-cmaes" test "x$enable_pythia6" = "xyes" && pl="$pl root-plugin-montecarlo-pythia6" test "x$enable_alien" = "xyes" && pl="$pl root-plugin-net-alien" test "x$enable_bonjour" = "xyes" && pl="$pl root-plugin-net-bonjour" @@ -6741,12 +6747,12 @@ if test "x$show_pkglist" = "xyes" ; then libroot-hist \ libroot-hist-spectrum \ libroot-io \ - libroot-math-cmaes \ libroot-math-foam \ libroot-math-genvector \ libroot-math-mathcore \ libroot-math-matrix \ libroot-math-minuit \ + libroot-math-cmaes \ libroot-math-mlp \ libroot-math-physics \ libroot-math-quadp \ @@ -6869,9 +6875,18 @@ fi if test -d star ; then rm -rf star fi +if test -d cint ; then + rm -rf cint +fi if test -d include/cint ; then rm -rf include/cint fi +if test -d include/Cintex ; then + rm -rf include/Cintex +fi +if test -d include/Reflex ; then + rm -rf include/Reflex +fi if test -d graf2d/freetype/src/freetype-2.3.5 ; then rm -rf graf2d/freetype/src/freetype-2.3.5 fi @@ -6902,6 +6917,9 @@ fi if test -d core/editline ; then rm -rf core/editline fi +if test -d core/globals ; then + rm -rf core/globals +fi if test -d net/xrootd ; then rm -rf net/xrootd fi @@ -6914,10 +6932,9 @@ fi rm -f lib/libRXML* bin/libRXML* etc/system.rootmap \ etc/svninfo.txt lib/libProofGui* bin/libProofGui* \ lib/libMySQL* bin/libMySQL* lib/libGedOld* bin/libGedOld* \ - lib/libSQL.* bin/libSQL.* \ + lib/libSQL.* bin/libSQL.* core/utils/src/rootcint_tmp \ lib/libASPluginGS.* bin/g2rootold* bin/ptest main/src/ptest.* \ math/mathcore/src/G__MathCore32.* \ - tmva/src/G__TMVA.* graf3d/eve/src/G__Eve.* \ xrootd/src/headers.d include/Xpm.h \ asimage/src/headers.d asimage/src/G__ASImageGS.* \ core/utils/src/rootcint7.cxx core/utils/src/RStl7.cxx \ @@ -6925,13 +6942,68 @@ rm -f lib/libRXML* bin/libRXML* etc/system.rootmap \ core/metautils/src/RConversionRuleParser7.cxx \ core/meta/src/G__TCint.h core/meta/src/G__TCint.cxx \ core/thread/src/TLockFile.* proof/proofplayer/src/TFileMerger.* \ + core/base/src/ManualBase4.* tree/tree/src/ManualTree2.* \ graf2d/graf/src/G__Graf1.h graf2d/graf/src/G__Graf1.cxx \ graf2d/graf/src/G__Graf2.h graf2d/graf/src/G__Graf2.cxx \ + core/base/src/G__Base1.h core/base/src/G__Base2.h \ + core/base/src/G__Base3.h core/clib/src/G__Clib.h \ + core/cont/src/G__Cont.h core/macosx/src/G__Macosx.h \ + core/meta/src/G__Meta.h core/metautils/src/G__MetaUtils.h \ + core/textinput/src/G__TextInput.h core/unix/src/G__Unix.h \ + core/zip/src/G__Zip.h geom/geom/src/G__Geom1.h \ + geom/geom/src/G__Geom2.h graf3d/g3d/src/G__G3D.h \ + graf3d/gl/src/G__GL.h gui/gui/src/G__Gui1.h \ + gui/gui/src/G__Gui2.h gui/gui/src/G__Gui3.h \ + graf2d/x11ttf/src/G__X11TTF.h graf2d/x11/src/G__X11.cxx \ + graf3d/x3d/src/G__X3D.h \ + hist/spectrumpainter/src/G__Spectrum2Painter.h \ + io/io/src/G__IO.h io/sql/src/G__SQL.h io/xml/src/G__XML.h \ + math/mathcore/src/G__Math.h math/mathcore/src/G__MathFit.h \ + net/ldap/src/G__LDAP.h core/winnt/src/G__WinNT.h \ + graf3d/eve/src/G__Eve1.h graf3d/eve/src/G__Eve2.h \ + tmva/src/G__TMVA1.h tmva/src/G__TMVA2.h tmva/src/G__TMVA3.h \ + tmva/src/G__TMVA4.h roofit/roofitcore/src/G__RooFitCore1.h \ + roofit/roofitcore/src/G__RooFitCore2.h roofit/roofitcore/src/G__RooFitCore3.h \ + roofit/roofitcore/src/G__RooFitCore4.h \ + core/base/src/G__Base1.cxx core/base/src/G__Base2.cxx \ + core/base/src/G__Base3.cxx core/clib/src/G__Clib.cxx \ + core/cont/src/G__Cont.cxx core/macosx/src/G__Macosx.cxx \ + core/meta/src/G__Meta.cxx core/metautils/src/G__MetaUtils.cxx \ + core/textinput/src/G__TextInput.cxx core/unix/src/G__Unix.cxx \ + core/zip/src/G__Zip.cxx geom/geom/src/G__Geom1.cxx \ + geom/geom/src/G__Geom2.cxx graf3d/g3d/src/G__G3D.cxx \ + graf3d/gl/src/G__GL.cxx gui/gui/src/G__Gui1.cxx \ + gui/gui/src/G__Gui2.cxx gui/gui/src/G__Gui3.cxx \ + hist/spectrumpainter/src/G__Spectrum2Painter.cxx \ + io/io/src/G__IO.cxx io/sql/src/G__SQL.cxx io/xml/src/G__XML.cxx \ + math/mathcore/src/G__Math.cxx math/mathcore/src/G__MathFit.cxx \ + net/ldap/src/G__LDAP.cxx core/winnt/src/G__WinNT.cxx \ + graf3d/eve/src/G__Eve1.cxx graf3d/eve/src/G__Eve2.cxx \ + graf2d/x11ttf/src/G__X11TTF.cxx graf2d/x11/src/G__X11.cxx \ + graf3d/x3d/src/G__X3D.cxx \ + roofit/roofitcore/src/G__RooFitCore1.cxx \ + roofit/roofitcore/src/G__RooFitCore2.cxx \ + roofit/roofitcore/src/G__RooFitCore3.cxx \ + roofit/roofitcore/src/G__RooFitCore4.cxx \ + tmva/src/G__TMVA1.cxx tmva/src/G__TMVA2.cxx tmva/src/G__TMVA3.cxx \ + tmva/src/G__TMVA4.cxx \ net/net/src/TAS3File.* net/net/src/TGSFile.* net/net/src/THTTPMessage.* \ etc/daemons/olbd.rc.d etc/daemons/cmsd.rc.d etc/daemons/xrootd.rc.d \ bin/cmsd bin/xprep bin/xrd bin/xrdcp bin/xrdgsiproxy bin/xrdpwdadmin \ bin/xrdsssadmin bin/xrdstagetool bin/xrootd lib/libXrd* \ - bin/drop_from_path + bin/drop_from_path bin/genreflex bin/genreflex.bat bin/genreflex-rootcint \ + bin/genreflex-rootcint.bat lib/libcomplexDict.rootmap \ + lib/libdequeDict.rootmap lib/liblistDict.rootmap lib/libmap2Dict.rootmap \ + lib/libmapDict.rootmap lib/libmultimap2Dict.rootmap \ + lib/libmultimapDict.rootmap lib/libmultisetDict.rootmap \ + lib/libsetDict.rootmap lib/libvalarrayDict.rootmap lib/libvectorDict.rootmap \ + include/TListOfTypes.h lib/*_RootCling.rootmap bin/rlibmap + +# if previous build was in non-c++11 mode, run "make maintainer-clean" first +run_maintainer_clean="no" +if `grep '#undef R__USE_CXX11' $CONFIGUREOUT > /dev/null 2>&1` ; then + run_maintainer_clean="yes" +fi ###################################################################### # @@ -6980,7 +7052,6 @@ if test ! "x$haveconfig" = "x" ; then if test "x$mandir" = "x"; then mandir=$prefix/share/man/man1; fi if test "x$datadir" = "x"; then datadir=$prefix/share/root; fi if test "x$macrodir" = "x"; then macrodir=$datadir/macros; fi - if test "x$cintincdir" = "x"; then cintincdir=$libdir/cint; fi if test "x$iconpath" = "x"; then iconpath=$datadir/icons; fi if test "x$srcdir" = "x"; then srcdir=$datadir/src; fi if test "x$fontdir" = "x"; then fontdir=$datadir/fonts; fi @@ -7029,7 +7100,6 @@ else datadir=\$\(ROOTSYS\) mandir=\$\(ROOTSYS\)/man/man1 macrodir=\$\(ROOTSYS\)/macros - cintincdir=\$\(ROOTSYS\)/cint iconpath=\$\(ROOTSYS\)/icons srcdir=\$\(ROOTSYS\)/src fontdir=\$\(ROOTSYS\)/fonts @@ -7108,6 +7178,7 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@buildglew@|$enable_builtin_glew|" \ -e "s|@builtinfreetype@|$enable_builtin_freetype|" \ -e "s|@builtinpcre@|$enable_builtin_pcre|" \ + -e "s|@builtinllvm@|$enable_builtin_llvm|" \ -e "s|@hasxrd@|$enable_xrootd|" \ -e "s|@castorincdir@|$castorincdir|" \ -e "s|@castorlib@|$castorlib|" \ @@ -7116,10 +7187,6 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@chirpincdir@|$chirpincdir|" \ -e "s|@chirplib@|$chirplib|" \ -e "s|@chirplibdir@|$chirplibdir|" \ - -e "s|@cintmaxstruct@|$cintmaxstruct|" \ - -e "s|@cintmaxtypedef@|$cintmaxtypedef|" \ - -e "s|@cintlongline@|$cintlongline|" \ - -e "s|@cintincdir@|$cintincdir|" \ -e "s|@cppunit@|$cppunit|" \ -e "s|@datadir@|$datadir|" \ -e "s|@davixincdir@|$davixincdir|" \ @@ -7128,14 +7195,10 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@comerrlibdir@|$comerrlibdir|" \ -e "s|@cryptolib@|$cryptolib|" \ -e "s|@cryptolibdir@|$cryptolibdir|" \ - -e "s|@cmaeslibdir@|$cmaeslibdir|" \ - -e "s|@cmaeslib@|$cmaeslib|" \ - -e "s|@cmaesincdir@|$cmaesincdir|" \ -e "s|@davixlib@|$davixlib|" \ -e "s|@davixlibdir@|$davixlibdir|" \ -e "s|@dcaplib@|$dcaplib|" \ -e "s|@dcaplibdir@|$dcaplibdir|" \ - -e "s|@dicttype@|$dicttype|" \ -e "s|@docdir@|$docdir|" \ -e "s|@elispdir@|$elispdir|" \ -e "s|@buildgenvector@|$enable_genvector|" \ @@ -7158,16 +7221,17 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@lzmaincdir@|$lzmaincdir|" \ -e "s|@lzmalib@|$lzmalib|" \ -e "s|@lzmalibdir@|$lzmalibdir|" \ - -e "s|@buildcintex@|$enable_cintex|" \ - -e "s|@buildcling@|$enable_cling|" \ - -e "s|@buildreflex@|$enable_reflex|" \ -e "s|@buildroofit@|$enable_roofit|" \ -e "s|@buildminuit2@|$enable_minuit2|" \ - -e "s|@buildcmaes@|$enable_cmaes|" \ + -e "s|@buildcmaes@|$enable_cmaes|" \ + -e "s|@cmaeslibdir@|$cmaeslibdir|" \ + -e "s|@cmaeslib@|$cmaeslib|" \ + -e "s|@cmaesincdir@|$cmaesincdir|" \ -e "s|@buildunuran@|$enable_unuran|" \ -e "s|@buildvc@|$enable_vc|" \ -e "s|@buildvdt@|$enable_vdt|" \ -e "s|@buildgdml@|$enable_gdml|" \ + -e "s|@buildgeocad@|$enable_geocad|" \ -e "s|@buildmonalisa@|$enable_monalisa|" \ -e "s|@buildtable@|$enable_table|" \ -e "s|@buildtmva@|$enable_tmva|" \ @@ -7184,6 +7248,7 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@glitelib@|$glitelib|" \ -e "s|@glitelibdir@|$glitelibdir|" \ -e "s|@gaw_cppflags@|$gaw_cppflags|" \ + -e "s|@ctorsinitarray@|$ctorsinitarray|" \ < Makefile.tmp > Makefile.tmpp mv Makefile.tmpp Makefile.tmp @@ -7235,6 +7300,9 @@ sed -e "s|@globusincdir@|$globusincdir|" \ -e "s|@mysqlincdir@|$mysqlincdir|" \ -e "s|@mysqllib@|$mysqllib|" \ -e "s|@mysqllibdir@|$mysqllibdir|" \ + -e "s|@occincdir@|$occincdir|" \ + -e "s|@occlib@|$occlib|" \ + -e "s|@occlibdir@|$occlibdir|" \ -e "s|@odbcincdir@|$odbcincdir|" \ -e "s|@odbclib@|$odbclib|" \ -e "s|@odbclibdir@|$odbclibdir|" \ @@ -7360,6 +7428,7 @@ sed -e "s|@srcdir@|$ac_srcdir|" \ -e "s|@buildnetxng@|$buildnetxng|" \ -e "s|@c++11@|$enable_cxx11|" \ -e "s|@libc++@|$enable_libcxx|" \ + -e "s|@werror@|$enable_werror|" \ < Makefile.tmp > $MAKEOUT rm -f Makefile.tmp @@ -7382,6 +7451,7 @@ sed -e "s|@altcc@|$altcc|" \ -e "s|@altcxx@|$altcxx|" \ -e "s|@altf77@|$altf77|" \ -e "s|@altld@|$altld|" \ + -e "s|@gcctoolchain@|$gcctoolchain|" \ < Makefile-comp.tmp > $MAKECOMPOUT rm -f Makefile-comp.tmp @@ -7394,7 +7464,6 @@ message "Writing $CONFIGUREOUT" sed \ -e "s|@architecture@|$arch|" \ -e "s|@bindir@|$bindir|" \ - -e "s|@cintincdir@|$cintincdir|" \ -e "s|@datadir@|$datadir|" \ -e "s|@docdir@|$docdir|" \ -e "s|@etcdir@|$etcdir|" \ @@ -7410,18 +7479,19 @@ sed \ -e "s|@hasmathmore@|$hasmathmore|" \ -e "s|@haspthread@|$haspthread|" \ -e "s|@hasxft@|$hasxft|" \ - -e "s|@hascling@|$hascling|" \ -e "s|@hascocoa@|$hascocoa|" \ -e "s|@hasvc@|$hasvc|" \ -e "s|@usec++11@|$usecxx11|" \ -e "s|@uselibc++@|$uselibcxx|" \ + -e "s|@hasllvm@|$hasllvm|" \ + -e "s|@llvmdir@|$llvmdir|" \ < RConfigure.tmp > RConfigure-out.tmp rm -f RConfigure.tmp # only update $CONFIGUREOUT when different if test -f $CONFIGUREOUT; then diff RConfigure-out.tmp $CONFIGUREOUT > /dev/null; status=$?; - if [ "$status" -ne "0" ]; then + if [ "$status" -ne "0" ] && [ "x$run_maintainer_clean" = "xno" ]; then mv -f RConfigure-out.tmp $CONFIGUREOUT else rm -f RConfigure-out.tmp @@ -7530,7 +7600,6 @@ sed -e "s|@architecture@|$arch|" \ -e "s|@features@|$features|" \ -e "s|@winrtdebug@|$enable_winrtdebug|"\ -e "s|@configargs@|$configargs|" \ - -e "s|@dicttype@|$dicttype|" \ -e "s|@pythonvers@|$pythonvers|" \ -e "s|@alloclibdir@|$alloclibdir|" \ -e "s|@alloclib@|$alloclib|" \ @@ -7725,60 +7794,6 @@ else result "done" fi -#--------------------------------------------------------------------- -# bin/genreflex(.bat), bin/genreflex-rootcint(.bat) -# -if test "x$enable_reflex" = "xyes"; then - libdirreflex=$libdir - if test "x$haveconfig" = "x" ; then - libdirreflex='$0; if readlink $dir > /dev/null 2>\&1; then lndir=`readlink $dir`; dir=`dirname $dir`; lndir=`dirname $lndir`; dir=`cd $dir \&\& cd $lndir \&\& pwd \|\| echo $lndir`; else dir=`dirname ${dir}`; fi; dir=${dir}/../lib' - fi - modpath="" - if test "x$platform" = "xwin32"; then - modpath=';dir=`cygpath -m $dir`' - fi - - message "Writing $GENREFLEXSHOUT" - cat $GENREFLEXSHIN | sed -e "s|@libdir@|$libdirreflex$modpath|g" > $GENREFLEXSHOUT - chmod a+x $GENREFLEXSHOUT - result "done" - if test "x$platform" = "xwin32"; then - message "Writing $GENREFLEXBATOUT" - if test "x$haveconfig" = "x" ; then - libdirreflex='%~d0%~p0\\..\\lib' - else - libdirreflex=`cygpath -m $libdir` - fi - - cat $GENREFLEXBATIN | sed -e "s|@libdir@|$libdirreflex|g" > $GENREFLEXBATOUT - chmod a+x $GENREFLEXBATOUT - result "done" - fi - - message "Writing $GENREFLEXROOTCINTSHOUT" - libdirreflex=$libdir - if test "x$haveconfig" = "x" ; then - libdirreflex='`dirname $0`/../lib' - fi - cat $GENREFLEXROOTCINTSHIN | sed -e "s|@libdir@|$libdirreflex|g" > $GENREFLEXROOTCINTSHOUT - chmod a+x $GENREFLEXROOTCINTSHOUT - result "done" - - if test "x$platform" = "xwin32"; then - message "Writing $GENREFLEXROOTCINTBATOUT" - if test "x$haveconfig" = "x" ; then - libdirreflex='%~d0%~p0\\..\\lib' - else - libdirreflex=`cygpath -m $libdir` - fi - cat $GENREFLEXROOTCINTBATIN | sed -e "s|@libdir@|$libdirreflex|g" > $GENREFLEXROOTCINTBATOUT - chmod a+x $GENREFLEXROOTCINTBATOUT - result "done" - fi -else - rm -f bin/genreflex* -fi - #--------------------------------------------------------------------- # config.status # @@ -7838,5 +7853,11 @@ if test "x$issue_explicitlink_warning" = "xyes"; then result "*** please remove them first using: rm -f lib/*.so." result "" fi +if [ "x$run_maintainer_clean" = "xyes" ]; then + result "*** Cleaning up previous non-C++11 build products, using:" + result "*** $gnumake maintainer-clean;$0 `cat config.status 2>/dev/null`" + $gnumake maintainer-clean + $0 `cat config.status 2>/dev/null` +fi exit 0 From ebe6df69c25963f76aeb50c8c9c1358cc4d06315 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 6 May 2014 09:47:20 +0200 Subject: [PATCH 03/98] adding cmaes repository --- math/cmaes/CMakeLists.txt | 13 ++ math/cmaes/Module.mk | 140 +++++++++++ math/cmaes/inc/CMAESMinimizer.h | 314 +++++++++++++++++++++++++ math/cmaes/inc/LinkDef.h | 30 +++ math/cmaes/src/CMAESMinimizer.cxx | 374 ++++++++++++++++++++++++++++++ tutorials/fit/cmaesGausFit.C | 82 +++++++ 6 files changed, 953 insertions(+) create mode 100644 math/cmaes/CMakeLists.txt create mode 100644 math/cmaes/Module.mk create mode 100644 math/cmaes/inc/CMAESMinimizer.h create mode 100644 math/cmaes/inc/LinkDef.h create mode 100644 math/cmaes/src/CMAESMinimizer.cxx create mode 100644 tutorials/fit/cmaesGausFit.C diff --git a/math/cmaes/CMakeLists.txt b/math/cmaes/CMakeLists.txt new file mode 100644 index 0000000000000..5efa39df31e14 --- /dev/null +++ b/math/cmaes/CMakeLists.txt @@ -0,0 +1,13 @@ +############################################################################ +# CMakeLists.txt file for building ROOT math/cmaes package +############################################################################ + +ROOT_USE_PACKAGE(math/mathcore) +ROOT_USE_PACKAGE(hist/hist) + +add_definitions(-DWARNINGMSG -DUSE_ROOT_ERROR) + +ROOT_GENERATE_DICTIONARY(G__cmaes *.h cmaes/*.h MODULE cmaes LINKDEF LinkDef.h) + +ROOT_LINKER_LIBRARY(cmaes *.cxx G__cmaes.cxx DEPENDENCIES MathCore Hist) +ROOT_INSTALL_HEADERS() \ No newline at end of file diff --git a/math/cmaes/Module.mk b/math/cmaes/Module.mk new file mode 100644 index 0000000000000..1f6c8f5724264 --- /dev/null +++ b/math/cmaes/Module.mk @@ -0,0 +1,140 @@ +# Module.ml for cmaes module. + +MODNAME := cmaes +MODDIR := $(ROOT_SRCDIR)/math/$(MODNAME) +MODDIRS := $(MODDIR)/src +MODDIRI := $(MODDIR)/inc + +CMAESDIR := $(MODDIR) +CMAESDIRS := $(CMAESDIR)/src +CMAESDIRI := $(CMAESDIR)/inc +#CMAESDIRT :=$(call stripsrc,$(CMAESDIR)/test) + +CMAESBASEVERS := cmaes-1_0_0 +CMAESBASESRCS := $(MODDIRS)/$(CMAESBASEVERS).tar.gz +CMAESBASEDIRS := $(MODDIRS)/$(CMAESBASEVERS) +CMAESBASEDIRI := -I$(MODDIRS)/$(CMAESBASEVERS) +CMAESBASEETAG := $(MODDIRS)/headers.d + +##### liblcg_cmaes ##### +ifeq ($(PLATFORM),win32) +CMAESBASELIBA := $(CMAESBASEDIRS)/libcmaesbase.lib +CMAESBASELIB := $(LPATH)/libcmaesbase.lib +ifeq (debug,$(findstring debug,$(ROOTBUILD))) +CMAESBASEBLD = "DEBUG=1" +else +CMAESBASEBLD = "" +endif +else +CMAESBASELIBA := $(CMAESBASEDIRS)/src/.libs/liblcg_cmaes.a +CMAESBASELIB := $(LPATH)/libcmaesbase.a +endif +CMAESBASEDEP := $(CMAESBASELIB) + +##### libcmaes ##### +CMAESL := $(MODDIRI)/LinkDef.h +CMAESDS := $(call stripsrc,$(MODDIRS)/G__cmaes.cxx) +CMAESDO := $(CMAESDS:.cxx=.o) +CMAESDH := $(CMAESDS:.cxx=.h) + +CMAESAH := $(filter-out $(MODDIRI)/LinkDef%,$(wildcard $(MODDIRI)/*.h)) +CMAESBH := $(filter-out $(MODDIRI)/cmaes/LinkDef%,$(wildcard $(MODDIRI)/cmaes/*.h)) +CMAESH := $(CMAESAH) $(CMAESBH) +CMAESS := $(filter-out $(MODDIRS)/G__%,$(wildcard $(MODDIRS)/*.cxx)) +CMAESO := $(call stripsrc,$(CMAESS:.cxx=.o)) + +CMAESDEP := $(CMAESO:.o=.d) $(CMAESDO:.o=.d) + +CMAESLIB := $(LPATH)/libcmaesroot.$(SOEXT) +CMAESMAP := $(CMAESLIB:.$(SOEXT)=.rootmap) + +# use this compiler option if want to optimize object allocation in cmaes +# NOTE: using this option one loses the thread safety. +# It is worth to use only for minimization of cheap (non CPU intensive) functions +#CXXFLAGS += -DMN_USE_STACK_ALLOC + +# used in the main Makefile +ALLHDRS += $(patsubst $(MODDIRI)/%.h,include/%.h,$(CMAESH)) +ALLLIBS += $(CMAESLIB) +ALLMAPS += $(CMAESMAP) + +# include all dependency files +INCLUDEFILES += $(CMAESDEP) + +##### local rules ##### +.PHONY: all-$(MODNAME) clean-$(MODNAME) distclean-$(MODNAME) \ + test-$(MODNAME) + +include/cmaes/%.h: $(CMAESDIRI)/cmaes/%.h + @(if [ ! -d "include/cmaes" ]; then \ + mkdir -p include/cmaes; \ + fi) + cp $< $@ + +include/%.h: $(CMAESDIRI)/%.h + cp $< $@ + +$(CMAESLIB): $(CMAESO) $(CMAESDO) $(ORDER_) $(MAINLIBS) $(CMAESLIBDEP) + @$(MAKELIB) $(PLATFORM) $(LD) "$(LDFLAGS)" \ + "$(SOFLAGS)" libcmaesroot.$(SOEXT) $@ \ + "$(CMAESO) $(CMAESDO)" "-lcmaes -lMathCore" "$(CMAESLIBEXTRA)" + +$(call pcmrule,MINUIT2) + $(noop) + +$(CMAESDS): $(CMAESH) $(CMAESL) $(ROOTCLINGEXE) $(call pcmdep,CMAES) + $(MAKEDIR) + @echo "Generating dictionary $@..." + $(ROOTCLINGSTAGE2) -f $@ $(call dictModule,CMAES) -I$(CMAESINCDIR) -I/usr/include/eigen3 -c $(CMAESH) $(CMAESL) + +$(CMAESMAP): $(CMAESH) $(CMAESL) $(ROOTCLINGEXE) $(call pcmdep,CMAES) + $(MAKEDIR) + @echo "Generating rootmap $@..." + $(ROOTCLINGSTAGE2) -r $(CMAESDS) $(call dictModule,CMAES) -c $(CMAESH) $(CMAESL) + +all-$(MODNAME): $(CMAESLIB) + +#test-$(MODNAME): all-$(MODNAME) +#ifneq ($(ROOT_OBJDIR),$(ROOT_SRCDIR)) +# @$(INSTALL) $(CMAESDIR)/test $(CMAESDIRT) +#endif + @cd $(CMAESDIRT) && $(MAKE) ROOTCONFIG=../../../bin/root-config + +clean-$(MODNAME): + @rm -f $(CMAESO) $(CMAESDO) + +clean:: clean-$(MODNAME) + +distclean-$(MODNAME): clean-$(MODNAME) + @rm -f $(CMAESDEP) $(CMAESDS) $(CMAESDH) $(CMAESLIB) \ + $(CMAESMAP) + @rm -rf include/cmaes +ifneq ($(ROOT_OBJDIR),$(ROOT_SRCDIR)) + @rm -rf $(CMAESDIRT) +else + @cd $(CMAESDIRT) && $(MAKE) distclean ROOTCONFIG=../../../bin/root-config +endif + +distclean:: distclean-$(MODNAME) + +##### extra rules ###### +$(CMAESO): CXXFLAGS += -DWARNINGMSG -DUSE_ROOT_ERROR +$(CMAESDO): CXXFLAGS += -DWARNINGMSG -DUSE_ROOT_ERROR +#for thread -safet +#$(CMAESO): CXXFLAGS += -DCMAES_THREAD_SAFE +# for openMP +#ifneq ($(USE_PARALLEL_CMAES),) +#ifneq ($(USE_OPENMP),) +#$(CMAESO): CXXFLAGS += -DCMAES_THREAD_SAFE -DCMAES_PARALLEL_OPENMP +#math/cmaes/src/Numerical2PGradientCalculator.o: +$(CMAESO):CXXFLAGS += -D_GLIBCXX_PARALLEL -fopenmp +$(CMAESDO):CXXFLAGS += -D_GLIBCXX_PARALLEL -fopenmp +$(CMAESLIB):LDFLAGS += -fopenmp +#endif + +$(CMAESO):CXXFLAGS += -I$(CMAESINCDIR) -I/usr/include/eigen3 +$(CMAESDO):CXXFLAGS += -I$(CMAESINCDIR) -I/usr/include/eigen3 +$(CMAESDS):CXXFLAGS += -I$(CMAESINCDIR) -I/usr/include/eigen3 +$(CMAESLIB):LDFLAGS += $(CMAESLIBDIR) +# Optimize dictionary with stl containers. +$(CMAESDO): NOOPT = $(OPT) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h new file mode 100644 index 0000000000000..44904fac4fbfd --- /dev/null +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -0,0 +1,314 @@ +/** + * CMA-ES, Covariance Matrix Evolution Strategy + * Copyright (c) 2014 INRIA + * Author: Emmanuel Benazera + * + * This file is part of libcmaes. + * + * libcmaes is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libcmaes is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libcmaes. If not, see . + */ + +#ifndef ROOT_CMAES_CMAESMinimizer +#define ROOT_CMAES_CMAESMinimizer + +#ifndef ROOT_Math_Minimizer +#include "Math/Minimizer.h" +#endif + +#ifndef ROOT_Math_IFunctionfwd +#include "Math/IFunctionfwd.h" +#endif + +#include "cmaes.h" + +using namespace libcmaes; + +namespace ROOT +{ + namespace cmaes + { + + class TCMAESMinimizer : public ROOT::Math::Minimizer + { + public: + + /** + * Default constructor + */ + TCMAESMinimizer(); // CMAES_DEFAULT + + /** + * Constructor with a char (used by PM) + */ + TCMAESMinimizer(const char *type); + + /** + * Destructor + */ + virtual ~TCMAESMinimizer(); + + private: + // blocking copy constructor. + TCMAESMinimizer(const TCMAESMinimizer &m); + + /** + * assignment operator. + */ + TCMAESMinimizer& operator = (const TCMAESMinimizer &rhs); + + public: + + // clear resources (parameters) for consecutives minimizations + virtual void Clear(); + + /// set the function to minimize + virtual void SetFunction(const ROOT::Math::IMultiGenFunction & func); + + /// set gradient the function to minimize + //virtual void SetFunction(const ROOT::Math::IMultiGradFunction & func); + + /// set free variable + virtual bool SetVariable(unsigned int ivar, const std::string & name, double val, double step); + + /// set lower limit variable (override if minimizer supports them ) + virtual bool SetLowerLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double lower ); + /// set upper limit variable (override if minimizer supports them ) + virtual bool SetUpperLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double upper ); + /// set upper/lower limited variable (override if minimizer supports them ) + virtual bool SetLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double /* lower */, double /* upper */); + /// set fixed variable (override if minimizer supports them ) + //virtual bool SetFixedVariable(unsigned int /* ivar */, const std::string & /* name */, double /* val */); + /// set variable + virtual bool SetVariableValue(unsigned int ivar, double val); + // set variable values + virtual bool SetVariableValues(const double * val); + /// set the step size of an already existing variable + //virtual bool SetVariableStepSize(unsigned int ivar, double step ); + /// set the lower-limit of an already existing variable + virtual bool SetVariableLowerLimit(unsigned int ivar, double lower); + /// set the upper-limit of an already existing variable + virtual bool SetVariableUpperLimit(unsigned int ivar, double upper); + /// set the limits of an already existing variable + virtual bool SetVariableLimits(unsigned int ivar, double lower, double upper); + /// fix an existing variable + //virtual bool FixVariable(unsigned int ivar); + /// release an existing variable + //virtual bool ReleaseVariable(unsigned int ivar); + /// query if an existing variable is fixed (i.e. considered constant in the minimization) + /// note that by default all variables are not fixed + //virtual bool IsFixedVariable(unsigned int ivar) const; + /// get variable settings in a variable object (like ROOT::Fit::ParamsSettings) + virtual bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings & varObj) const; + /// get name of variables (override if minimizer support storing of variable names) + virtual std::string VariableName(unsigned int ivar) const; + /// get index of variable given a variable given a name + /// return -1 if variable is not found + virtual int VariableIndex(const std::string & name) const; + + /** + method to perform the minimization. + Return false in case the minimization did not converge. In this case a + status code different than zero is set + (retrieved by the derived method Minimizer::Status() )" + + status = 1 : Covariance was made pos defined + status = 2 : Hesse is invalid + status = 3 : Edm is above max + status = 4 : Reached call limit + status = 5 : Any other failure + */ + virtual bool Minimize(); + + /// return minimum function value + virtual double MinValue() const; + + /// return expected distance reached from the minimum + //TODO. + virtual double Edm() const { return -1.0;/*return fState.Edm();*/ } + + /// return pointer to X values at the minimum + virtual const double * X() const; + + /// return pointer to gradient values at the minimum + virtual const double * MinGradient() const { return 0; } // not available in CMAES + + /// number of function calls to reach the minimum + virtual unsigned int NCalls() const; + + /// this is <= Function().NDim() which is the total + /// number of variables (free+ constrained ones) + virtual unsigned int NDim() const { return fDim; } + + /// number of free variables (real dimension of the problem) + /// this is <= Function().NDim() which is the total + virtual unsigned int NFree() const { return fFreeDim; } + + /// minimizer provides error and error matrix + //TODO: true. + virtual bool ProvidesError() const { return false; } + + /// return errors at the minimum + //TODO. + virtual const double * Errors() const { return 0;} + + /** + return covariance matrix elements + if the variable is fixed or const the value is zero + The ordering of the variables is the same as in errors and parameter value. + This is different from the direct interface of Minuit2 or TMinuit where the + values were obtained only to variable parameters + */ + virtual double CovMatrix(unsigned int i, unsigned int j) const; + + + /** + Fill the passed array with the covariance matrix elements + if the variable is fixed or const the value is zero. + The array will be filled as cov[i *ndim + j] + The ordering of the variables is the same as in errors and parameter value. + This is different from the direct interface of Minuit2 or TMinuit where the + values were obtained only to variable parameters + */ + virtual bool GetCovMatrix(double * cov) const; + + /** + Fill the passed array with the Hessian matrix elements + The Hessian matrix is the matrix of the second derivatives + and is the inverse of the covariance matrix + If the variable is fixed or const the values for that variables are zero. + The array will be filled as h[i *ndim + j] + */ + //virtual bool GetHessianMatrix(double * h) const; + + + /** + return the status of the covariance matrix + status = -1 : not available (inversion failed or Hesse failed) + status = 0 : available but not positive defined + status = 1 : covariance only approximate + status = 2 : full matrix but forced pos def + status = 3 : full accurate matrix + + */ + virtual int CovMatrixStatus() const { return 3; } + /** + return correlation coefficient between variable i and j. + If the variable is fixed or const the return value is zero + */ + virtual double Correlation(unsigned int i, unsigned int j ) const; + + /** + get global correlation coefficient for the variable i. This is a number between zero and one which gives + the correlation between the i-th variable and that linear combination of all other variables which + is most strongly correlated with i. + If the variable is fixed or const the return value is zero + */ + virtual double GlobalCC(unsigned int i) const; + + /** + get the minos error for parameter i, return false if Minos failed + A minimizaiton must be performed befre, return false if no minimization has been done + In case of Minos failed the status error is updated as following + status += 10 * minosStatus where the minos status is: + status = 1 : maximum number of function calls exceeded when running for lower error + status = 2 : maximum number of function calls exceeded when running for upper error + status = 3 : new minimum found when running for lower error + status = 4 : new minimum found when running for upper error + status = 5 : any other failure + + */ + //TODO + virtual bool GetMinosError(unsigned int i, double & errLow, double & errUp, int = 0); + + /** + scan a parameter i around the minimum. A minimization must have been done before, + return false if it is not the case + */ + //TODO + virtual bool Scan(unsigned int i, unsigned int & nstep, double * x, double * y, double xmin = 0, double xmax = 0); + + /** + find the contour points (xi,xj) of the function for parameter i and j around the minimum + The contour will be find for value of the function = Min + ErrorUp(); + */ + //TODO + virtual bool Contour(unsigned int i, unsigned int j, unsigned int & npoints, double *xi, double *xj); + + + /** + perform a full calculation of the Hessian matrix for error calculation + If a valid minimum exists the calculation is done on the minimum point otherwise is performed + in the current set values of parameters + Status code of minimizer is updated according to the following convention (in case Hesse failed) + status += 100*hesseStatus where hesse status is: + status = 1 : hesse failed + status = 2 : matrix inversion failed + status = 3 : matrix is not pos defined + */ + //virtual bool Hesse(); + + + /// return reference to the objective function + ///virtual const ROOT::Math::IGenFunction & Function() const; + + /// print result of minimization + virtual void PrintResults(); + + /// set an object to trace operation for each iteration + /// The object muust implement operator() (unsigned int, MinimumState & state) + //void SetTraceObject(MnTraceObject & obj); + + /// set storage level = 1 : store all iteration states (default) + /// = 0 : store only first and last state to save memory + void SetStorageLevel(int level); + + /// return the minimizer state (containing values, step size , etc..) + //const ROOT::Minuit2::MnUserParameterState & State() { return fState; } + + protected: + + // protected function for accessing the internal Minuit2 object. Needed for derived classes + + //virtual const ROOT::Minuit2::ModularFunctionMinimizer * GetMinimizer() const { return fMinimizer; } + + //TODO. + //virtual void SetMinimizer( ROOT::Minuit2::ModularFunctionMinimizer * m) { fMinimizer = m; } + + //TODO. + //void SetMinimizerType( ROOT::Minuit2::EMinimizerType type); + + //virtual const ROOT::Minuit2::FCNBase * GetFCN() const { return fMinuitFCN; } + + /// examine the minimum result + //bool ExamineMinimum(const ROOT::Minuit2::FunctionMinimum & min); + + private: + unsigned int fDim; // dimension of the function to be minimized + unsigned int fFreeDim; // Number of free dimensions. + //int fMinimizer; // minimizer algo. + const ROOT::Math::IMultiGenFunction *fObjFunc = nullptr; + std::vector fLBounds; // Lower bounds of variables + std::vector fUBounds; // Upper bounds of variables + std::vector fVariablesType; // 0 for free variable, 1 for fixed variable, 2 for lower bounded, 3 for upper bounded, 4 for lower and upper bounded. + std::vector fInitialX; + std::vector fNames; // Names of the variables. + std::vector fInitialSigma; // User-set Initial step-size for each variables. + CMASolutions fCMAsols; + mutable std::vector fGlobalCC; // vector of global correlation coefficients. + }; + + } // end namespace cmaes +} // end namespace ROOT + +#endif diff --git a/math/cmaes/inc/LinkDef.h b/math/cmaes/inc/LinkDef.h new file mode 100644 index 0000000000000..c5a1c5e2825ba --- /dev/null +++ b/math/cmaes/inc/LinkDef.h @@ -0,0 +1,30 @@ +/** + * CMA-ES, Covariance Matrix Evolution Strategy + * Copyright (c) 2014 INRIA + * Author: Emmanuel Benazera + * + * This file is part of libcmaes. + * + * libcmaes is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libcmaes is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libcmaes. If not, see . + */ + +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class TCMAESMinimizer; + +#endif diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx new file mode 100644 index 0000000000000..e7d04810a642c --- /dev/null +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -0,0 +1,374 @@ +/** + * CMA-ES, Covariance Matrix Evolution Strategy + * Copyright (c) 2014 INRIA + * Author: Emmanuel Benazera + * + * This file is part of libcmaes. + * + * libcmaes is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libcmaes is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libcmaes. If not, see . + */ + +#include "CMAESMinimizer.h" +#include "Math/IFunctionfwd.h" // fObjFunc +#include "Math/IOptions.h" +#include "Math/Error.h" +#include "Fit/ParameterSettings.h" + +#ifdef USE_ROOT_ERROR +#include "TROOT.h" +#endif + +namespace ROOT +{ + namespace cmaes + { + + TCMAESMinimizer::TCMAESMinimizer() + :Minimizer(),fDim(0),fFreeDim(0) + { + } + + TCMAESMinimizer::TCMAESMinimizer(const char *type) + :Minimizer(),fDim(0),fFreeDim(0) + { + //std::string algoname(type); + // tolower() is not an std function (Windows) + //std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int(*)(int)) tolower ); + } + + TCMAESMinimizer::TCMAESMinimizer(const TCMAESMinimizer &m) + :Minimizer() + { + } + + TCMAESMinimizer& TCMAESMinimizer::operator = (const TCMAESMinimizer &rhs) + { + if (this == &rhs) return *this; + return *this; + } + + TCMAESMinimizer::~TCMAESMinimizer() + { + } + + void TCMAESMinimizer::Clear() + { + fCMAsols = CMASolutions(); + fGlobalCC.clear(); + } + + void TCMAESMinimizer::SetFunction(const ROOT::Math::IMultiGenFunction &fun) + { + fObjFunc = &fun; + fDim = fun.NDim(); + } + + bool TCMAESMinimizer::SetVariable(unsigned int ivar, const std::string & name, double val, double step) + { + if (ivar > fInitialX.size() ) { + MATH_ERROR_MSG("TCMAESMinimizer::SetVariable","ivar out of range"); + return false; + } + if (ivar == fInitialX.size() ) { + fInitialX.push_back(val); + fNames.push_back(name); + fInitialSigma.push_back(step); + fLBounds.push_back(0); + fUBounds.push_back(0); + if (step==0.){ + fVariablesType.push_back(1); + } + else { + fFreeDim++; + fVariablesType.push_back(0); + } + } + else { + if (step==0.) { + if (fInitialSigma[ivar]!=0.) { //Constraining a free variable. + fFreeDim--; + fVariablesType[ivar] = 1; + } + } + else { + if (fInitialSigma[ivar]==0.) { //Freeing a constrained variable + fFreeDim++; + fVariablesType[ivar] = 0; + } + } + fInitialX[ivar] = val; + fNames[ivar] = name; + fInitialSigma[ivar] = step; + } + return true; + } + + bool TCMAESMinimizer::SetLowerLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double lower ) + { + if (lower > val) { + MATH_WARN_MSG("TCMAESMinimizer::SetLowerLimitedVariable", "Starting point set into the unfeasible domain"); // fix with val=lower; ? + } + bool r = SetVariable(ivar, name, val, step); + if (!r) return false; + fLBounds[ivar] = lower; + fVariablesType[ivar] = 2; + return true; + } + + bool TCMAESMinimizer::SetUpperLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double upper ) + { + if (upper > val) { + MATH_WARN_MSG("TCMAESMinimizer::SetUpperLimitedVariable", "Starting point set into the unfeasible domain"); + } + bool r = SetVariable(ivar, name, val, step); + if (!r) return false; + fUBounds[ivar] = upper; + fVariablesType[ivar] = 3; + return true; + } + + bool TCMAESMinimizer::SetLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double lower, double upper) + { + if (upper == lower) { + MATH_WARN_MSG("TCMAESMinimizer::SetLimitedVariable","Upper bound equal to lower bound. Variable is constrained to fixed value."); + return SetFixedVariable(ivar, name, val); + } + if (upper < lower) { + MATH_WARN_MSG("TCMAESMinimizer::SetLimitedVariable","Upper bound lesser than lower bound. Bounds exchanged."); + double temp(upper); + upper = lower; + lower = temp; + } + if (val < lower || val > upper) { + MATH_WARN_MSG("TCMAESMinimizer::SetLimitedVariable", "Starting point set into the unfeasible domain"); + } + bool r = SetVariable(ivar, name, val, step); + if (!r) return false; + fLBounds[ivar] = lower; + fUBounds[ivar] = upper; + fVariablesType[ivar] = 4; + return true; + } + + bool TCMAESMinimizer::SetVariableValue(unsigned int ivar, double val ) + { + if (ivar >= fInitialX.size() ) { + //TODO string that gives value of ivar and fInitialX.size() + MATH_ERROR_MSG("TCMAESMinimizer::SetVariableValue","ivar out of range"); + return false; + } + if (fVariablesType[ivar] == 2 || fVariablesType[ivar] == 4) { + if (fLBounds[ivar] > val) { + MATH_WARN_MSG("TCMAESMinimizer::SetVariableValue", "Starting point set into the unfeasible domain"); + } + } + if (fVariablesType[ivar] == 3 || fVariablesType[ivar] == 4) { + if (fUBounds[ivar] < val) { + MATH_WARN_MSG("TCMAESMinimizer::SetVariableValue", "Starting point set into the unfeasible domain"); + } + } + fInitialX[ivar] = val; + return true; + } + + bool TCMAESMinimizer::SetVariableValues(const double * x) + { + if (x == NULL) + { + MATH_WARN_MSG("TCMAESMinimizer::SetVariableValues", "No values given, no change to the starting point."); + return false; + } + unsigned int i; + for (i=0; i fLBounds.size()) + return false; + fLBounds[ivar] = lower; + fVariablesType[ivar] = 2; + return true; + } + + bool TCMAESMinimizer::SetVariableUpperLimit(unsigned int ivar, double upper) + { + if (ivar > fUBounds.size()) + return false; + fUBounds[ivar] = upper; + fVariablesType[ivar] = 3; + return true; + } + + bool TCMAESMinimizer::SetVariableLimits(unsigned int ivar, double lower, double upper) + { + if (ivar >= fLBounds.size() || ivar >= fUBounds.size()) + return false; + fLBounds[ivar] = lower; + fUBounds[ivar] = upper; + fVariablesType[ivar] = 4; + return true; + } + + bool TCMAESMinimizer::GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const + { + if (ivar >= fInitialX.size()) + { + MATH_ERROR_MSG("TCMAESMinimizer::GetVariableSettings","wrong variable index"); + return false; + } + varObj.Set(fNames.at(ivar),fInitialX.at(ivar),false); //XXX: not sure of last param type. + if (fVariablesType.at(ivar) == 4) + varObj.SetLimits(fLBounds.at(ivar),fUBounds.at(ivar)); + else if (fVariablesType.at(ivar) == 3) + varObj.SetUpperLimit(fUBounds.at(ivar)); + else if (fVariablesType.at(ivar) == 2) + varObj.SetLowerLimit(fLBounds.at(ivar)); + return true; + } + + std::string TCMAESMinimizer::VariableName(unsigned int ivar) const + { + if (ivar >= fInitialX.size()) + return std::string(); + return fNames.at(ivar); + } + + int TCMAESMinimizer::VariableIndex(const std::string &name) const + { + for (unsigned int i=0;i fInitialX.size()) { + MATH_ERROR_MSG("TCMAESMinimizer::Minimize","Dimension larger than initial X size's"); + return false; + } + if (fDim < fInitialX.size()) { + MATH_WARN_MSG("TCMAESMinimizer::Minimize","Dimension smaller than initial X size's"); + } + + //ROOT::Math::IOptions *cmaesOpt = ROOT::Math::MinimizerOptions::FindDefault("cmaes"); //TODO. + + //TODO: phenotype / genotype. + + CMAParameters<> cmaparams(fDim); + //TODO: x0, sigma0, ... + FitFunc ffit = [this](const double *x, const int N) + { + return (*fObjFunc)(x); + }; + fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); + //fCMAsols = cmaes<>([this](const double *x, const int N){ return (*fObjFunc)(x);},cmaparams); //TODO: use bounds as needed. + fStatus = fCMAsols._run_status; //TODO: convert so that to match that of Minuit2 ? + return fCMAsols._run_status >= 0; + } + + double TCMAESMinimizer::MinValue() const + { + return fCMAsols.best_candidate()._fvalue; + } + + const double* TCMAESMinimizer::X() const + { + //TODO: return pheno x when applicable (in solution object). + return fCMAsols.best_candidate()._x.data(); // beware that lasts as long as the fCMAsols object only. + } + + unsigned int TCMAESMinimizer::NCalls() const + { + return fCMAsols._nevals; + } + + double TCMAESMinimizer::CovMatrix(unsigned int i, unsigned int j) const + { + return fCMAsols._cov(i,j); + } + + bool TCMAESMinimizer::GetCovMatrix(double *cov) const + { + std::copy(fCMAsols._cov.data(),fCMAsols._cov.data()+fCMAsols._cov.size(),cov); + return true; + } + + double TCMAESMinimizer::Correlation(unsigned int i, unsigned int j) const + { + return std::sqrt(std::abs(fCMAsols._cov(i,i)*fCMAsols._cov(j,j))); + } + + double TCMAESMinimizer::GlobalCC(unsigned int i) const + { + // original Minuit paper says: + // \rho_k^2 = 1 - [C_{kk}C_{kk}^{-1}]^{-1} + if (fGlobalCC.empty()) // need to pre-compute the vector coefficient + { + dMat covinv = fCMAsols._cov.inverse(); + for (int i=0;i 0.0) + fGlobalCC.push_back(0.0); + else fGlobalCC.push_back(std::sqrt(1.0 - 1.0/denom)); + } + } + return fGlobalCC.at(i); + } + + bool TCMAESMinimizer::GetMinosError(unsigned int i, double &errLow, double &errUp, int j) + { + //TODO. + return false; + } + + bool TCMAESMinimizer::Scan(unsigned int i, unsigned int &nstep, double *x, double *y, double xmin, double xmax) + { + //TODO. + return false; + } + + bool TCMAESMinimizer::Contour(unsigned int i, unsigned int j, unsigned int &npoints, double *xi, double *xj) + { + //TODO. + return false; + } + + void TCMAESMinimizer::PrintResults() + { + std::cout << "CMAESMinimizer : Valid minimum - status = " << fStatus << std::endl; + std::cout << "FVAL = " << MinValue() << std::endl; + std::cout << "Nfcn = " << NCalls() << std::endl; + for (unsigned int i=0;i +#include + + +void testGausFit( std::string type = "cmaes", int n = 1000) { + + gRandom = new TRandom3(); + + TVirtualFitter::SetDefaultFitter(type.c_str() ); + + std::string name; + name = "h1_" + type; + TH1D * h1 = new TH1D(name.c_str(),"Chi2 Fit",100, -5, 5. ); + /*name = "h2_" + type; + TH1D * h2 = new TH1D(name.c_str(),"Chi2 Fit with Minos Error",100, -5, 5. ); + name = "h3_" + type; + TH1D * h3 = new TH1D(name.c_str(),"Chi2 Fit with Integral and Minos",100, -5, 5. ); + name = "h4_" + type; + TH1D * h4 = new TH1D(name.c_str(),"Likelihood Fit with Minos Error",100, -5, 5. );*/ + + gStyle->SetOptStat(1111111); + gStyle->SetOptFit(1111111); + + for (int i = 0; i < n; ++i) { + double x = gRandom->Gaus(0,1); + h1->Fill( x ); + /* h2->Fill( x ); + h3->Fill( x ); + h4->Fill( x ); */ + } + + std::string cname = type + "Canvas" ; + std::string ctitle = type + " Gaussian Fit" ; + //TCanvas *c1 = new TCanvas(cname.c_str(),cname.c_str(),10,10,900,900); + //c1->Divide(2,2); + + //c1->cd(1); + cout << "\nDo Fit 1\n"; + h1->Fit("gaus","Q"); + h1->Draw(); + /*c1->cd(2); + cout << "\nDo Fit 2\n"; + h2->Fit("gaus","VE"); + h2->Draw(); + c1->cd(3); + cout << "\nDo Fit 3\n"; + h3->Fit("gaus","IE"); + h3->Draw(); + c1->cd(4); + cout << "\nDo Fit 4\n"; + h4->Fit("gaus","VLE"); + h4->Draw();*/ + +} + +void cmaesGausFit() { + + int n = 1000; + testGausFit("cmaes",n); +} + + + From e69e1d13f9e24eb095eb23703c000a1afecd3ea7 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 6 May 2014 10:25:06 +0200 Subject: [PATCH 04/98] added cmaes plugin --- etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C diff --git a/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C b/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C new file mode 100644 index 0000000000000..e9ec6b1725fe5 --- /dev/null +++ b/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C @@ -0,0 +1,5 @@ +void P090_TCMAESMinimizer() +{ + gPluginMgr->AddHandler("ROOT::Math::Minimizer", "cmaes", "ROOT::cmaes::TCMAESMinimizer", + "cmaes", "TCMAESMinimizer(const char *)"); +} From 4df6185f29a9d8c8d461ff43ed8ce3703cb23603 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 6 May 2014 11:44:56 +0200 Subject: [PATCH 05/98] first working auto-loaded cmaes --- etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C | 2 +- math/cmaes/inc/CMAESMinimizer.h | 1 + math/cmaes/src/CMAESMinimizer.cxx | 4 +++- tutorials/fit/cmaesGausFit.C | 9 ++++++--- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C b/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C index e9ec6b1725fe5..25bbcf863826e 100644 --- a/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C +++ b/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C @@ -1,5 +1,5 @@ void P090_TCMAESMinimizer() { gPluginMgr->AddHandler("ROOT::Math::Minimizer", "cmaes", "ROOT::cmaes::TCMAESMinimizer", - "cmaes", "TCMAESMinimizer(const char *)"); + "cmaesroot", "TCMAESMinimizer(const char *)"); } diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 44904fac4fbfd..63148af4c16ad 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -306,6 +306,7 @@ namespace ROOT std::vector fInitialSigma; // User-set Initial step-size for each variables. CMASolutions fCMAsols; mutable std::vector fGlobalCC; // vector of global correlation coefficients. + mutable std::vector fValues; // X values. }; } // end namespace cmaes diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index e7d04810a642c..ad7cdef0282e2 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -298,7 +298,9 @@ namespace ROOT const double* TCMAESMinimizer::X() const { //TODO: return pheno x when applicable (in solution object). - return fCMAsols.best_candidate()._x.data(); // beware that lasts as long as the fCMAsols object only. + //std::cout << "X=" << fCMAsols.best_candidate()._x.transpose() << std::endl; + fValues.assign(fCMAsols.best_candidate()._x.data(),fCMAsols.best_candidate()._x.data()+fDim*sizeof(double)); + return &fValues.front(); } unsigned int TCMAESMinimizer::NCalls() const diff --git a/tutorials/fit/cmaesGausFit.C b/tutorials/fit/cmaesGausFit.C index 86178ca763b50..66024ec1cae76 100644 --- a/tutorials/fit/cmaesGausFit.C +++ b/tutorials/fit/cmaesGausFit.C @@ -16,15 +16,17 @@ #include "TVirtualFitter.h" #include "TPaveLabel.h" #include "TStyle.h" +#include "TSystem.h" +#include "TFile.h" +#include "TROOT.h" #include #include - void testGausFit( std::string type = "cmaes", int n = 1000) { gRandom = new TRandom3(); - + TVirtualFitter::SetDefaultFitter(type.c_str() ); std::string name; @@ -73,7 +75,8 @@ void testGausFit( std::string type = "cmaes", int n = 1000) { } void cmaesGausFit() { - + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); int n = 1000; testGausFit("cmaes",n); } From 073302ac3a32316abb43e9f4951093a5c76725c6 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 6 May 2014 13:27:39 +0200 Subject: [PATCH 06/98] fixed cmaes wrapper + added likelihood gaussian fit to tutorial --- math/cmaes/src/CMAESMinimizer.cxx | 15 +++++++++++++-- tutorials/fit/cmaesGausFit.C | 15 +++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index ad7cdef0282e2..98dd1af833302 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -65,7 +65,15 @@ namespace ROOT void TCMAESMinimizer::Clear() { fCMAsols = CMASolutions(); + fDim = 0; fFreeDim = 0; + fLBounds.clear(); + fUBounds.clear(); + fVariablesType.clear(); + fInitialX.clear(); + fInitialSigma.clear(); + fNames.clear(); fGlobalCC.clear(); + fValues.clear(); } void TCMAESMinimizer::SetFunction(const ROOT::Math::IMultiGenFunction &fun) @@ -298,8 +306,11 @@ namespace ROOT const double* TCMAESMinimizer::X() const { //TODO: return pheno x when applicable (in solution object). - //std::cout << "X=" << fCMAsols.best_candidate()._x.transpose() << std::endl; - fValues.assign(fCMAsols.best_candidate()._x.data(),fCMAsols.best_candidate()._x.data()+fDim*sizeof(double)); + std::cout << "X=" << fCMAsols.best_candidate()._x.transpose() << std::endl; + fValues.clear(); + Candidate bc = fCMAsols.best_candidate(); + for (int i=0;iGaus(0,1); - h1->Fill( x ); + h1->Fill( x ); + h1bis->Fill( x ); /* h2->Fill( x ); h3->Fill( x ); h4->Fill( x ); */ @@ -52,13 +55,17 @@ void testGausFit( std::string type = "cmaes", int n = 1000) { std::string cname = type + "Canvas" ; std::string ctitle = type + " Gaussian Fit" ; - //TCanvas *c1 = new TCanvas(cname.c_str(),cname.c_str(),10,10,900,900); - //c1->Divide(2,2); + TCanvas *c1 = new TCanvas(cname.c_str(),cname.c_str(),10,10,900,900); + c1->Divide(2,1); - //c1->cd(1); + c1->cd(1); cout << "\nDo Fit 1\n"; h1->Fit("gaus","Q"); h1->Draw(); + c1->cd(2); + cout << "\nDo Fit 1bis\n"; + h1bis->Fit("gaus","VLE"); + h1bis->Draw(); /*c1->cd(2); cout << "\nDo Fit 2\n"; h2->Fit("gaus","VE"); From a687d1c7e8a94d0fc1756a8bd085c3e213964012 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 6 May 2014 16:00:43 +0200 Subject: [PATCH 07/98] connecting error estimates to cmaes wrapper --- math/cmaes/inc/CMAESMinimizer.h | 4 ++-- math/cmaes/src/CMAESMinimizer.cxx | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 63148af4c16ad..8d33e96e463e2 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -159,8 +159,7 @@ namespace ROOT virtual bool ProvidesError() const { return false; } /// return errors at the minimum - //TODO. - virtual const double * Errors() const { return 0;} + virtual const double* Errors() const; /** return covariance matrix elements @@ -307,6 +306,7 @@ namespace ROOT CMASolutions fCMAsols; mutable std::vector fGlobalCC; // vector of global correlation coefficients. mutable std::vector fValues; // X values. + mutable std::vector fErrors; // X errors. }; } // end namespace cmaes diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 98dd1af833302..53979c0e85052 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -74,6 +74,7 @@ namespace ROOT fNames.clear(); fGlobalCC.clear(); fValues.clear(); + fErrors.clear(); } void TCMAESMinimizer::SetFunction(const ROOT::Math::IMultiGenFunction &fun) @@ -306,7 +307,7 @@ namespace ROOT const double* TCMAESMinimizer::X() const { //TODO: return pheno x when applicable (in solution object). - std::cout << "X=" << fCMAsols.best_candidate()._x.transpose() << std::endl; + //std::cout << "X=" << fCMAsols.best_candidate()._x.transpose() << std::endl; fValues.clear(); Candidate bc = fCMAsols.best_candidate(); for (int i=0;i Date: Thu, 15 May 2014 13:10:21 +0200 Subject: [PATCH 09/98] default CMA-ES progress function set to no output --- math/cmaes/src/CMAESMinimizer.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 53979c0e85052..6ca175ff7db65 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -293,7 +293,8 @@ namespace ROOT { return (*fObjFunc)(x); }; - fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); + ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; + fCMAsols = libcmaes::cmaes<>(ffit,cmaparams,pfunc); //fCMAsols = cmaes<>([this](const double *x, const int N){ return (*fObjFunc)(x);},cmaparams); //TODO: use bounds as needed. fStatus = fCMAsols._run_status; //TODO: convert so that to match that of Minuit2 ? return fCMAsols._run_status >= 0; From 45715cdf4ecc7a515ccee0115f4f295d5177997e Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 16 May 2014 16:35:36 +0200 Subject: [PATCH 10/98] added support for box-type constraints with CMA-ES --- math/cmaes/inc/CMAESMinimizer.h | 5 +++-- math/cmaes/src/CMAESMinimizer.cxx | 37 +++++++++++++++++++++++-------- math/mathcore/src/Factory.cxx | 4 ++-- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 8d33e96e463e2..786c4056332d8 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -293,8 +293,8 @@ namespace ROOT //bool ExamineMinimum(const ROOT::Minuit2::FunctionMinimum & min); private: - unsigned int fDim; // dimension of the function to be minimized - unsigned int fFreeDim; // Number of free dimensions. + unsigned int fDim = 0; // dimension of the function to be minimized + unsigned int fFreeDim = 0; // Number of free dimensions. //int fMinimizer; // minimizer algo. const ROOT::Math::IMultiGenFunction *fObjFunc = nullptr; std::vector fLBounds; // Lower bounds of variables @@ -307,6 +307,7 @@ namespace ROOT mutable std::vector fGlobalCC; // vector of global correlation coefficients. mutable std::vector fValues; // X values. mutable std::vector fErrors; // X errors. + bool fWithBounds = false; // whether using box-type constraints as required by parameters. }; } // end namespace cmaes diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 6ca175ff7db65..0349aa55d4441 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -29,18 +29,20 @@ #include "TROOT.h" #endif +using namespace libcmaes; + namespace ROOT { namespace cmaes { TCMAESMinimizer::TCMAESMinimizer() - :Minimizer(),fDim(0),fFreeDim(0) + :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false) { } TCMAESMinimizer::TCMAESMinimizer(const char *type) - :Minimizer(),fDim(0),fFreeDim(0) + :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false) { //std::string algoname(type); // tolower() is not an std function (Windows) @@ -48,7 +50,7 @@ namespace ROOT } TCMAESMinimizer::TCMAESMinimizer(const TCMAESMinimizer &m) - :Minimizer() + :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false) { } @@ -93,8 +95,8 @@ namespace ROOT fInitialX.push_back(val); fNames.push_back(name); fInitialSigma.push_back(step); - fLBounds.push_back(0); - fUBounds.push_back(0); + fLBounds.push_back(-std::numeric_limits::max()); + fUBounds.push_back(std::numeric_limits::max()); if (step==0.){ fVariablesType.push_back(1); } @@ -132,6 +134,7 @@ namespace ROOT if (!r) return false; fLBounds[ivar] = lower; fVariablesType[ivar] = 2; + fWithBounds = true; return true; } @@ -144,6 +147,7 @@ namespace ROOT if (!r) return false; fUBounds[ivar] = upper; fVariablesType[ivar] = 3; + fWithBounds = true; return true; } @@ -167,6 +171,7 @@ namespace ROOT fLBounds[ivar] = lower; fUBounds[ivar] = upper; fVariablesType[ivar] = 4; + fWithBounds = true; return true; } @@ -211,6 +216,7 @@ namespace ROOT return false; fLBounds[ivar] = lower; fVariablesType[ivar] = 2; + fWithBounds = true; return true; } @@ -220,6 +226,7 @@ namespace ROOT return false; fUBounds[ivar] = upper; fVariablesType[ivar] = 3; + fWithBounds = true; return true; } @@ -230,6 +237,7 @@ namespace ROOT fLBounds[ivar] = lower; fUBounds[ivar] = upper; fVariablesType[ivar] = 4; + fWithBounds = true; return true; } @@ -286,15 +294,26 @@ namespace ROOT //ROOT::Math::IOptions *cmaesOpt = ROOT::Math::MinimizerOptions::FindDefault("cmaes"); //TODO. //TODO: phenotype / genotype. - - CMAParameters<> cmaparams(fDim); - //TODO: x0, sigma0, ... + FitFunc ffit = [this](const double *x, const int N) { return (*fObjFunc)(x); }; ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; - fCMAsols = libcmaes::cmaes<>(ffit,cmaparams,pfunc); + + //TODO: x0, sigma0, ... + if (fWithBounds) + { + GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); + CMAParameters> cmaparams(fDim,-1,-1.0,0,gp); + cmaparams._quiet = true; + fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + } + else + { + CMAParameters<> cmaparams(fDim); + fCMAsols = libcmaes::cmaes<>(ffit,cmaparams,pfunc); + } //fCMAsols = cmaes<>([this](const double *x, const int N){ return (*fObjFunc)(x);},cmaparams); //TODO: use bounds as needed. fStatus = fCMAsols._run_status; //TODO: convert so that to match that of Minuit2 ? return fCMAsols._run_status >= 0; diff --git a/math/mathcore/src/Factory.cxx b/math/mathcore/src/Factory.cxx index 7827ca5d26b7b..a9c02acb96da4 100644 --- a/math/mathcore/src/Factory.cxx +++ b/math/mathcore/src/Factory.cxx @@ -90,7 +90,7 @@ ROOT::Math::Minimizer * ROOT::Math::Factory::CreateMinimizer(const std::string & minim = s1.c_str(); } - std::cout << "minimizerType: " << minimizerType << " / minim: " << minim << std::endl; + //std::cout << "minimizerType: " << minimizerType << " / minim: " << minim << std::endl; if (minimizerType.empty() ) minim = ROOT::Math::MinimizerOptions::DefaultMinimizerType().c_str(); @@ -115,7 +115,7 @@ ROOT::Math::Minimizer * ROOT::Math::Factory::CreateMinimizer(const std::string & else std::cout << "Error creating Minimizer " << minimizerType << " " << algoType << std::endl; #endif - std::cout << "min: " << min << std::endl; + //std::cout << "min: " << min << std::endl; return min; } std::cout << "returning 0\n"; From c9e85a85dddf8a635aaa70e2305360b4b173706a Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 19 May 2014 14:59:25 +0200 Subject: [PATCH 11/98] added support to multiple flavors of CMA-ES --- math/cmaes/inc/CMAESMinimizer.h | 2 +- math/cmaes/src/CMAESMinimizer.cxx | 23 +++++++++++++++++++++-- math/mathcore/src/Factory.cxx | 11 +++++++++-- math/mathcore/src/MinimizerOptions.cxx | 11 +++++++++-- tutorials/fit/cmaesGausFit.C | 1 + 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 786c4056332d8..93d36e0784721 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -295,7 +295,7 @@ namespace ROOT private: unsigned int fDim = 0; // dimension of the function to be minimized unsigned int fFreeDim = 0; // Number of free dimensions. - //int fMinimizer; // minimizer algo. + int fMinimizer = CMAES_DEFAULT; // minimizer algo. const ROOT::Math::IMultiGenFunction *fObjFunc = nullptr; std::vector fLBounds; // Lower bounds of variables std::vector fUBounds; // Upper bounds of variables diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 0349aa55d4441..4eea85b4e0e7c 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -44,9 +44,27 @@ namespace ROOT TCMAESMinimizer::TCMAESMinimizer(const char *type) :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false) { - //std::string algoname(type); + std::string algoname(type); // tolower() is not an std function (Windows) - //std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int(*)(int)) tolower ); + std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int(*)(int)) tolower ); + if (algoname == "cmaes") + fMinimizer = CMAES_DEFAULT; + else if (algoname == "ipop") + fMinimizer = IPOP_CMAES; + else if (algoname == "bipop") + fMinimizer = BIPOP_CMAES; + else if (algoname == "acmaes") + fMinimizer = aCMAES; + else if (algoname == "aipop") + fMinimizer = aIPOP_CMAES; + else if (algoname == "abipop") + fMinimizer = aBIPOP_CMAES; + else if (algoname == "sepcmaes") + fMinimizer = sepCMAES; + else if (algoname == "sepipop") + fMinimizer = sepIPOP_CMAES; + else if (algoname == "sepbipop") + fMinimizer = sepBIPOP_CMAES; } TCMAESMinimizer::TCMAESMinimizer(const TCMAESMinimizer &m) @@ -307,6 +325,7 @@ namespace ROOT GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); CMAParameters> cmaparams(fDim,-1,-1.0,0,gp); cmaparams._quiet = true; + cmaparams._algo = fMinimizer; fCMAsols = libcmaes::cmaes>(ffit,cmaparams); } else diff --git a/math/mathcore/src/Factory.cxx b/math/mathcore/src/Factory.cxx index a9c02acb96da4..06eadedaa9d87 100644 --- a/math/mathcore/src/Factory.cxx +++ b/math/mathcore/src/Factory.cxx @@ -84,9 +84,10 @@ ROOT::Math::Minimizer * ROOT::Math::Factory::CreateMinimizer(const std::string & s1 = "Minuit"; minim = s1.c_str(); } - if (minimizerType == "cmaes") + if (minimizerType.find("cmaes")!=std::string::npos + ||minimizerType.find("ipop")!=std::string::npos) { - s1 = "cmaes"; + s1 = minimizerType; minim = s1.c_str(); } @@ -152,6 +153,12 @@ ROOT::Math::Minimizer * ROOT::Math::Factory::CreateMinimizer(const std::string & min = new TMinuitMinimizer(algoType.c_str()); #endif +#ifdef HAS_CMAES + if (minimizerType.find("cmaes") != std::string::npos + || minimizerType.find("ipop") != std::string::npos) + min = new ROOT::cmaes::TCMAESMinimizer(algoType.c_str()); +#endif + #ifdef R__HAS_MATHMORE // use GSL minimizer if (minimizerType == "GSL") diff --git a/math/mathcore/src/MinimizerOptions.cxx b/math/mathcore/src/MinimizerOptions.cxx index ece5fcd314199..8697a135d14a8 100644 --- a/math/mathcore/src/MinimizerOptions.cxx +++ b/math/mathcore/src/MinimizerOptions.cxx @@ -120,10 +120,17 @@ MinimizerOptions::MinimizerOptions(IOptions * extraOpts): else if (fMinimType == "Fumili2") { fMinimType = "Minuit2"; fAlgoType = "Fumili"; - } + } + else if (fMinimType.find("cmaes")!=std::string::npos + || fMinimType.find("ipop")!=std::string::npos) + { + fAlgoType = fMinimType; + fMinimType = "cmaes"; + } else if (fMinimType == "GSLMultiMin" && fAlgoType == "Migrad") fAlgoType = "BFGS2"; - + + // check if extra options exists (copy them if needed) if (!fExtraOptions) { IOptions * gopts = FindDefault( fMinimType.c_str() ); diff --git a/tutorials/fit/cmaesGausFit.C b/tutorials/fit/cmaesGausFit.C index dee765ba4896a..95b23e1c969b4 100644 --- a/tutorials/fit/cmaesGausFit.C +++ b/tutorials/fit/cmaesGausFit.C @@ -86,6 +86,7 @@ void cmaesGausFit() { gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); int n = 1000; testGausFit("cmaes",n); + //testGausFit("acmaes",n); } From 783d69182abd5abb165e08a44d44e5ff6e222e3a Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 19 May 2014 15:12:33 +0200 Subject: [PATCH 12/98] added 1D histograms fitting benchmark for CMA-ES --- tutorials/fit/cmaesFitBench.C | 121 ++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 tutorials/fit/cmaesFitBench.C diff --git a/tutorials/fit/cmaesFitBench.C b/tutorials/fit/cmaesFitBench.C new file mode 100644 index 0000000000000..059482e155d5f --- /dev/null +++ b/tutorials/fit/cmaesFitBench.C @@ -0,0 +1,121 @@ +//+ Fitting 1-D histograms with cmaes +// Author: L. Moneta 10/2005 +// Author: E. Benazera 05/2014 + +/********************************************************************** + * * + * Copyright (c) 2014 INRIA * + * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * + * * + **********************************************************************/ + +#include "TH1.h" +#include "TF1.h" +#include "TCanvas.h" +#include "TStopwatch.h" +#include "TSystem.h" +#include "TRandom3.h" +#include "TVirtualFitter.h" +#include "TPaveLabel.h" +#include "TStyle.h" +#include "TMath.h" +#include "TROOT.h" +#include "TFrame.h" +#include "TSystem.h" + +//#include "Fit/FitConfig.h" + + +TF1 *fitFcn; +TH1 *histo; + +// Quadratic background function +Double_t background(Double_t *x, Double_t *par) { + return par[0] + par[1]*x[0] + par[2]*x[0]*x[0]; +} + +// Lorenzian Peak function +Double_t lorentzianPeak(Double_t *x, Double_t *par) { + return (0.5*par[0]*par[1]/TMath::Pi()) / + TMath::Max( 1.e-10,(x[0]-par[2])*(x[0]-par[2]) + .25*par[1]*par[1]); +} + +// Sum of background and peak function +Double_t fitFunction(Double_t *x, Double_t *par) { + return background(x,par) + lorentzianPeak(x,&par[3]); +} + +void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { + printf("\n*********************************************************************************\n"); + printf("\t %s \n",fitter); + printf("*********************************************************************************\n"); + + gRandom = new TRandom3(); + TStopwatch timer; + // timer.Start(); + TVirtualFitter::SetDefaultFitter(fitter); + //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); + pad->SetGrid(); + pad->SetLogy(); + fitFcn->SetParameters(1,1,1,6,.03,1); + fitFcn->Update(); + std::string title = std::string(fitter) + " fit bench"; + histo = new TH1D(fitter,title.c_str(),200,0,3); + + timer.Start(); + for (Int_t pass=0;passSetParameters(1,1,1,6,.03,1); + for (Int_t i=0;i<5000;i++) { + histo->Fill(fitFcn->GetRandom()); + } + histo->Fit(fitFcn,"Q0"); + } + + histo->Fit(fitFcn,"EV"); + timer.Stop(); + + (histo->GetFunction("fitFcn"))->SetLineColor(kRed+3); + gPad->SetFillColor(kYellow-10); + + + Double_t cputime = timer.CpuTime(); + printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter,npass,timer.RealTime(),cputime); + TPaveLabel *p = new TPaveLabel(0.45,0.7,0.88,0.8,Form("%s CPU= %g s",fitter,cputime),"brNDC"); + p->Draw(); + p->SetTextColor(kRed+3); + p->SetFillColor(kYellow-8); + pad->Update(); +} + +void cmaesFitBench(Int_t npass=20) { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + TH1::AddDirectory(kFALSE); + TCanvas *c1 = new TCanvas("FitBench","Fitting Demo",10,10,900,900); + c1->Divide(2,2); + c1->SetFillColor(kYellow-9); + // create a TF1 with the range from 0 to 3 and 6 parameters + fitFcn = new TF1("fitFcn",fitFunction,0,3,6); + fitFcn->SetNpx(200); + gStyle->SetOptFit(); + gStyle->SetStatY(0.6); + + //with Minuit2 + c1->cd(1); + DoFit("Minuit2",gPad,npass); + + //with Fumili + c1->cd(2); + DoFit("Fumili",gPad,npass); + + //with cmaes + c1->cd(3); + DoFit("cmaes",gPad,npass); + + //with sepcmaes + c1->cd(4); + DoFit("sepcmaes",gPad,npass); + + c1->SaveAs("FitBench.root"); +} From 9a119c541626174bca21bc06fbfbf4fe975b73c8 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 19 May 2014 18:03:41 +0200 Subject: [PATCH 13/98] fixed loading of libraries in CMA-ES tutorial hist fit --- tutorials/fit/cmaesFitBench.C | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tutorials/fit/cmaesFitBench.C b/tutorials/fit/cmaesFitBench.C index 059482e155d5f..ed83412351300 100644 --- a/tutorials/fit/cmaesFitBench.C +++ b/tutorials/fit/cmaesFitBench.C @@ -29,6 +29,8 @@ TF1 *fitFcn; TH1 *histo; +bool libloaded = false; + // Quadratic background function Double_t background(Double_t *x, Double_t *par) { return par[0] + par[1]*x[0] + par[2]*x[0]*x[0]; @@ -89,8 +91,12 @@ void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { } void cmaesFitBench(Int_t npass=20) { - gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); - gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + if (!libloaded) + { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + libloaded = true; + } TH1::AddDirectory(kFALSE); TCanvas *c1 = new TCanvas("FitBench","Fitting Demo",10,10,900,900); c1->Divide(2,2); @@ -116,6 +122,6 @@ void cmaesFitBench(Int_t npass=20) { //with sepcmaes c1->cd(4); DoFit("sepcmaes",gPad,npass); - + c1->SaveAs("FitBench.root"); } From e40d79d031203494f222d50c143a57d5efd95f93 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 19 May 2014 18:04:01 +0200 Subject: [PATCH 14/98] fixed status in libcmaes wrapper --- math/cmaes/src/CMAESMinimizer.cxx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 4eea85b4e0e7c..8c9ab88522430 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -317,24 +317,29 @@ namespace ROOT { return (*fObjFunc)(x); }; - ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; + //TODO: x0, sigma0, ... if (fWithBounds) { + //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); CMAParameters> cmaparams(fDim,-1,-1.0,0,gp); - cmaparams._quiet = true; cmaparams._algo = fMinimizer; + cmaparams._quiet = true; fCMAsols = libcmaes::cmaes>(ffit,cmaparams); } else { + //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; CMAParameters<> cmaparams(fDim); - fCMAsols = libcmaes::cmaes<>(ffit,cmaparams,pfunc); + cmaparams._algo = fMinimizer; + cmaparams._quiet = true; + fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); } - //fCMAsols = cmaes<>([this](const double *x, const int N){ return (*fObjFunc)(x);},cmaparams); //TODO: use bounds as needed. - fStatus = fCMAsols._run_status; //TODO: convert so that to match that of Minuit2 ? + if (fCMAsols._run_status >= 0) + fStatus = 0; //TODO: convert so that to match that of Minuit2 ? + else fStatus = 5; return fCMAsols._run_status >= 0; } From 78436789b5277e46e4182f1155efdf674ec53f18 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 20 May 2014 17:42:10 +0200 Subject: [PATCH 15/98] fixed initialization of parameters with CMA-ES --- math/cmaes/src/CMAESMinimizer.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 8c9ab88522430..5beec016b390a 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -320,20 +320,23 @@ namespace ROOT //TODO: x0, sigma0, ... + int lambda = -1; if (fWithBounds) { //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); - CMAParameters> cmaparams(fDim,-1,-1.0,0,gp); + CMAParameters> cmaparams(fDim,lambda,-1.0,0,gp); cmaparams._algo = fMinimizer; + cmaparams.set_x0(&fInitialX.front()); cmaparams._quiet = true; fCMAsols = libcmaes::cmaes>(ffit,cmaparams); } else { //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; - CMAParameters<> cmaparams(fDim); + CMAParameters<> cmaparams(fDim,lambda); cmaparams._algo = fMinimizer; + cmaparams.set_x0(&fInitialX.front()); cmaparams._quiet = true; fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); } From 8f03372206db9314d224c2c07bf08a2732cddf7e Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 20 May 2014 18:12:24 +0200 Subject: [PATCH 16/98] added 2D bench for cmaes --- tutorials/fit/cmaesFitBench2D.C | 99 +++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 tutorials/fit/cmaesFitBench2D.C diff --git a/tutorials/fit/cmaesFitBench2D.C b/tutorials/fit/cmaesFitBench2D.C new file mode 100644 index 0000000000000..e6cc605afc656 --- /dev/null +++ b/tutorials/fit/cmaesFitBench2D.C @@ -0,0 +1,99 @@ +// Author: L. Moneta 10/2005 +// Author: E. Benazera 05/2014 + +/********************************************************************** + * * + * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * + * * + **********************************************************************/ + +#include "TH1.h" +#include "TF1.h" +#include "TH2D.h" +#include "TF2.h" +#include "TCanvas.h" +#include "TStopwatch.h" +#include "TSystem.h" +#include "TRandom3.h" +#include "TVirtualFitter.h" +#include "TPaveLabel.h" +#include "TStyle.h" + + +TF2 *fitFcn; +TH2D *histo; + +// Quadratic background function +Double_t gaus2D(Double_t *x, Double_t *par) { + double t1 = x[0] - par[1]; + double t2 = x[1] - par[2]; + return par[0]* exp( - 0.5 * ( t1*t1/( par[3]*par[3]) + t2*t2 /( par[4]*par[4] ) ) ) ; +} + +// Sum of background and peak function +Double_t fitFunction(Double_t *x, Double_t *par) { + return gaus2D(x,par); +} + +void fillHisto(int n =10000) { + + gRandom = new TRandom3(); + for (int i = 0; i < n; ++i) { + double x = gRandom->Gaus(2,3); + double y = gRandom->Gaus(-1,4); + histo->Fill(x,y,1.); + } +} + +void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { + TStopwatch timer; + TVirtualFitter::SetDefaultFitter(fitter); + pad->SetGrid(); + fitFcn->SetParameters(100,0,0,2,7); + fitFcn->Update(); + + timer.Start(); + histo->Fit("fitFcn","0"); + timer.Stop(); + + histo->Draw(); + Double_t cputime = timer.CpuTime(); + printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter,npass,timer.RealTime(),cputime); + TPaveLabel *p = new TPaveLabel(0.5,0.7,0.85,0.8,Form("%s CPU= %g s",fitter,cputime),"brNDC"); + p->Draw(); + pad->Update(); +} + +void cmaesFitBench2D(int n = 100000) { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + TH1::AddDirectory(kFALSE); + TCanvas *c1 = new TCanvas("c1","Fitting Demo",10,10,900,900); + c1->Divide(2,2); + // create a TF1 with the range from 0 to 3 and 6 parameters + fitFcn = new TF2("fitFcn",fitFunction,-10,10,-10,10,5); + //fitFcn->SetNpx(200); + gStyle->SetOptFit(); + gStyle->SetStatY(0.6); + + histo = new TH2D("h2","2D Gauss",100,-10,10,100,-10,10); + fillHisto(n); + + int npass=0; + + //with Minuit2 + c1->cd(3); + DoFit("Minuit2",gPad,npass); + + //with Fumili + c1->cd(4); + DoFit("Fumili",gPad,npass); + + //with cmaes + c1->cd(1); + DoFit("cmaes",gPad,npass); + + //with sepcmaes + c1->cd(2); + DoFit("sepcmaes",gPad,npass); +} From 30b5b73e980f5af9d45b9bda66c59ee44c8a834d Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 20 May 2014 18:13:01 +0200 Subject: [PATCH 17/98] added explanations to hist 1D fit for cmaes --- tutorials/fit/cmaesFitBench.C | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tutorials/fit/cmaesFitBench.C b/tutorials/fit/cmaesFitBench.C index ed83412351300..c462619932208 100644 --- a/tutorials/fit/cmaesFitBench.C +++ b/tutorials/fit/cmaesFitBench.C @@ -71,10 +71,11 @@ void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { for (Int_t i=0;i<5000;i++) { histo->Fill(fitFcn->GetRandom()); } - histo->Fit(fitFcn,"Q0"); + //histo->Print("all"); + histo->Fit(fitFcn,"Q0"); // from TH1.cxx: Q: quiet, 0: do not plot } - histo->Fit(fitFcn,"EV"); + histo->Fit(fitFcn,"EV"); // E: use Minos, V: verbose. timer.Stop(); (histo->GetFunction("fitFcn"))->SetLineColor(kRed+3); @@ -123,5 +124,5 @@ void cmaesFitBench(Int_t npass=20) { c1->cd(4); DoFit("sepcmaes",gPad,npass); - c1->SaveAs("FitBench.root"); + //c1->SaveAs("FitBench.root"); } From 5d2237b4f3fe9915c2d2c4f2f914bb7d3f4e7946 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Wed, 21 May 2014 15:42:47 +0200 Subject: [PATCH 18/98] fixed parameters init for CMA-ES after refactoring of the libcmaes --- math/cmaes/src/CMAESMinimizer.cxx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 5beec016b390a..cf449b0352811 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -192,6 +192,11 @@ namespace ROOT fWithBounds = true; return true; } + + bool TCMAESMinimizer::SetFixedVariable(unsigned int ivar, const std::string &name, double val) + { + //TODO. + } bool TCMAESMinimizer::SetVariableValue(unsigned int ivar, double val ) { @@ -319,24 +324,22 @@ namespace ROOT }; - //TODO: x0, sigma0, ... + //TODO: sigma0, ... int lambda = -1; if (fWithBounds) { //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); - CMAParameters> cmaparams(fDim,lambda,-1.0,0,gp); + CMAParameters> cmaparams(fDim,&fInitialX.front(),-1.0,lambda,0,gp); cmaparams._algo = fMinimizer; - cmaparams.set_x0(&fInitialX.front()); cmaparams._quiet = true; fCMAsols = libcmaes::cmaes>(ffit,cmaparams); } else { //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; - CMAParameters<> cmaparams(fDim,lambda); + CMAParameters<> cmaparams(fDim,&fInitialX.front(),-1.0,lambda); cmaparams._algo = fMinimizer; - cmaparams.set_x0(&fInitialX.front()); cmaparams._quiet = true; fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); } From 8bb74707667b565a113d5a3a67a5cd3a7d1f0ef6 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Wed, 21 May 2014 15:59:05 +0200 Subject: [PATCH 19/98] provides error to true in CMAESMinimizer.h + preparing for fixed parameters --- math/cmaes/inc/CMAESMinimizer.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 93d36e0784721..ab7e9b476c21f 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -88,7 +88,7 @@ namespace ROOT /// set upper/lower limited variable (override if minimizer supports them ) virtual bool SetLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double /* lower */, double /* upper */); /// set fixed variable (override if minimizer supports them ) - //virtual bool SetFixedVariable(unsigned int /* ivar */, const std::string & /* name */, double /* val */); + virtual bool SetFixedVariable(unsigned int /* ivar */, const std::string & /* name */, double /* val */); /// set variable virtual bool SetVariableValue(unsigned int ivar, double val); // set variable values @@ -155,8 +155,7 @@ namespace ROOT virtual unsigned int NFree() const { return fFreeDim; } /// minimizer provides error and error matrix - //TODO: true. - virtual bool ProvidesError() const { return false; } + virtual bool ProvidesError() const { return true; } /// return errors at the minimum virtual const double* Errors() const; From 13db0b49a1bb8431387853cdfcbe1c42da9da438 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 26 May 2014 10:40:24 +0200 Subject: [PATCH 20/98] set default sigma0 for CMA-ES as the max step size across parameters --- math/cmaes/src/CMAESMinimizer.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index cf449b0352811..fc2b0388b194f 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -324,13 +324,14 @@ namespace ROOT }; - //TODO: sigma0, ... + double sigma0 = *std::max_element(fInitialSigma.begin(),fInitialSigma.end()); int lambda = -1; if (fWithBounds) { + Info("CMAESMinimizer","Minimizing with bounds"); //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); - CMAParameters> cmaparams(fDim,&fInitialX.front(),-1.0,lambda,0,gp); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0,lambda,0,gp); cmaparams._algo = fMinimizer; cmaparams._quiet = true; fCMAsols = libcmaes::cmaes>(ffit,cmaparams); @@ -338,7 +339,7 @@ namespace ROOT else { //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; - CMAParameters<> cmaparams(fDim,&fInitialX.front(),-1.0,lambda); + CMAParameters<> cmaparams(fDim,&fInitialX.front(),sigma0,lambda); cmaparams._algo = fMinimizer; cmaparams._quiet = true; fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); From 54d92df43f97af647ac75f63ffcfcdc7f0647a6e Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 26 May 2014 10:43:04 +0200 Subject: [PATCH 21/98] fixed multiple loading of external lib in fit tutorial for CMA-ES --- tutorials/fit/cmaesGausFit.C | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tutorials/fit/cmaesGausFit.C b/tutorials/fit/cmaesGausFit.C index 95b23e1c969b4..178a16932e1b6 100644 --- a/tutorials/fit/cmaesGausFit.C +++ b/tutorials/fit/cmaesGausFit.C @@ -23,6 +23,8 @@ #include #include +bool libloaded = false; + void testGausFit( std::string type = "cmaes", int n = 1000) { gRandom = new TRandom3(); @@ -81,9 +83,13 @@ void testGausFit( std::string type = "cmaes", int n = 1000) { } -void cmaesGausFit() { - gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); - gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); +void cmaesGausFit() { + if (!libloaded) + { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + libloaded = true; + } int n = 1000; testGausFit("cmaes",n); //testGausFit("acmaes",n); From 0664ca90274084c27bdce8b3fd0640dd944e6087 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 26 May 2014 20:28:57 +0200 Subject: [PATCH 22/98] introduced first MINOS version for CMA-ES + added control of ftolerance + added control of fixed variables and auto-maxiter stopping criteria --- math/cmaes/inc/CMAESMinimizer.h | 4 +- math/cmaes/src/CMAESMinimizer.cxx | 61 ++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index ab7e9b476c21f..ae02a3afad5f0 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -226,7 +226,6 @@ namespace ROOT status = 5 : any other failure */ - //TODO virtual bool GetMinosError(unsigned int i, double & errLow, double & errUp, int = 0); /** @@ -302,7 +301,10 @@ namespace ROOT std::vector fInitialX; std::vector fNames; // Names of the variables. std::vector fInitialSigma; // User-set Initial step-size for each variables. + std::map fFixedVariables; // fixed variables and values. CMASolutions fCMAsols; + CMAParameters<> fCMAparams; // params no bounds. + CMAParameters> fCMAparamsb; // params with bounds. mutable std::vector fGlobalCC; // vector of global correlation coefficients. mutable std::vector fValues; // X values. mutable std::vector fErrors; // X errors. diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index fc2b0388b194f..af9a963a27db6 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -25,6 +25,8 @@ #include "Math/Error.h" #include "Fit/ParameterSettings.h" +#include "errstats.h" // libcmaes extras. + #ifdef USE_ROOT_ERROR #include "TROOT.h" #endif @@ -91,6 +93,7 @@ namespace ROOT fVariablesType.clear(); fInitialX.clear(); fInitialSigma.clear(); + fFixedVariables.clear(); fNames.clear(); fGlobalCC.clear(); fValues.clear(); @@ -195,7 +198,7 @@ namespace ROOT bool TCMAESMinimizer::SetFixedVariable(unsigned int ivar, const std::string &name, double val) { - //TODO. + fFixedVariables.insert(std::pair(ivar,val)); } bool TCMAESMinimizer::SetVariableValue(unsigned int ivar, double val ) @@ -307,6 +310,7 @@ namespace ROOT return false; } if (fDim > fInitialX.size()) { + std::cout << "fDim=" << fDim << " / fInitialX size=" << fInitialX.size() << std::endl; MATH_ERROR_MSG("TCMAESMinimizer::Minimize","Dimension larger than initial X size's"); return false; } @@ -323,9 +327,18 @@ namespace ROOT return (*fObjFunc)(x); }; - + double sigma0 = *std::max_element(fInitialSigma.begin(),fInitialSigma.end()); int lambda = -1; + + if (gDebug > 0) + { + std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0 << " / lambda=" << lambda << " / fTol=" << fTol << " / with_bounds=" << fWithBounds << std::endl; + std::cout << "x0="; + std::copy(fInitialX.begin(),fInitialX.end(),std::ostream_iterator(std::cout," ")); + std::cout << std::endl; + } + if (fWithBounds) { Info("CMAESMinimizer","Minimizing with bounds"); @@ -333,17 +346,32 @@ namespace ROOT GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0,lambda,0,gp); cmaparams._algo = fMinimizer; - cmaparams._quiet = true; + if (gDebug > 0) + cmaparams._quiet = false; + else cmaparams._quiet = true; + for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) + cmaparams.set_fixed_p((*mit).first,(*mit).second); + cmaparams.set_ftolerance(fTol); + cmaparams.set_automaxiter(false); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + fCMAparamsb = cmaparams; } else { //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; CMAParameters<> cmaparams(fDim,&fInitialX.front(),sigma0,lambda); cmaparams._algo = fMinimizer; - cmaparams._quiet = true; + if (gDebug > 0) + cmaparams._quiet = false; + else cmaparams._quiet = true; + for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) + cmaparams.set_fixed_p((*mit).first,(*mit).second); + cmaparams.set_ftolerance(fTol); + cmaparams.set_automaxiter(false); fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); + fCMAparams = cmaparams; } + Info("CMAESMinimizer","optimization status=%i",fCMAsols._run_status); if (fCMAsols._run_status >= 0) fStatus = 0; //TODO: convert so that to match that of Minuit2 ? else fStatus = 5; @@ -417,8 +445,29 @@ namespace ROOT bool TCMAESMinimizer::GetMinosError(unsigned int i, double &errLow, double &errUp, int j) { - //TODO. - return false; + FitFunc ffit = [this](const double *x, const int N) + { + return (*fObjFunc)(x); + }; + + // runopt is a flag which specifies if only lower or upper error needs to be run. TODO: support for one bound only in libcmaes ? + int samplesize = 10; + if (gDebug > 0) + std::cerr << "Computing 'Minos' confidence interval with profile likelihood on parameter " << i << " / samplesize=" << samplesize << " / with_bounds=" << fWithBounds << std::endl; + pli le; + if (!fWithBounds) + { + fCMAparams.set_automaxiter(true); + le = errstats<>::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize); + } + else + { + fCMAparamsb.set_automaxiter(true); + le = errstats>::profile_likelihood(ffit,fCMAparamsb,fCMAsols,i,false,samplesize); + } + errLow = le._errmin; + errUp = le._errmax; + return true; } bool TCMAESMinimizer::Scan(unsigned int i, unsigned int &nstep, double *x, double *y, double xmin, double xmax) From 15c636f18a2f11d29155d7c6bd62619a396946f5 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 26 May 2014 20:29:26 +0200 Subject: [PATCH 23/98] added to CMA-ES packagte the same tests that are available for Minuit2 --- math/cmaes/test/CMakeLists.txt | 66 ++ math/cmaes/test/Makefile | 91 +++ math/cmaes/test/testMinimizer.cxx | 891 +++++++++++++++++++++++++++ math/cmaes/test/testNdimFit.cxx | 285 +++++++++ math/cmaes/test/testUnbinGausFit.cxx | 333 ++++++++++ math/cmaes/test/testUserFunc.cxx | 88 +++ 6 files changed, 1754 insertions(+) create mode 100644 math/cmaes/test/CMakeLists.txt create mode 100644 math/cmaes/test/Makefile create mode 100644 math/cmaes/test/testMinimizer.cxx create mode 100644 math/cmaes/test/testNdimFit.cxx create mode 100644 math/cmaes/test/testUnbinGausFit.cxx create mode 100644 math/cmaes/test/testUserFunc.cxx diff --git a/math/cmaes/test/CMakeLists.txt b/math/cmaes/test/CMakeLists.txt new file mode 100644 index 0000000000000..2b1401083af05 --- /dev/null +++ b/math/cmaes/test/CMakeLists.txt @@ -0,0 +1,66 @@ +project(minuit2-tests) +find_package(ROOT REQUIRED) + +include(${ROOT_USE_FILE}) +include_directories(${ROOT_INCLUDE_DIRS}) + +set(TestSource + testMinimizer.cxx +) + +set(TestSourceMnTutorial + MnTutorial/Quad1FMain.cxx + MnTutorial/Quad4FMain.cxx + MnTutorial/Quad8FMain.cxx + MnTutorial/Quad12FMain.cxx +) + +set(TestSourceMnSim + MnSim/DemoGaussSim.cxx + MnSim/DemoFumili.cxx + MnSim/PaulTest.cxx + MnSim/PaulTest2.cxx + MnSim/PaulTest3.cxx + MnSim/PaulTest4.cxx + MnSim/ReneTest.cxx + MnSim/ParallelTest.cxx + MnSim/demoMinimizer.cxx +) + + + + +#---For the simple Minuit2 tests build and defined them--------------- +foreach(file ${TestSourceMnTutorial}) + get_filename_component(testname ${file} NAME_WE) + ROOT_EXECUTABLE(${testname} ${file} LIBRARIES Minuit2) + ROOT_ADD_TEST(minuit2-${testname} COMMAND ${testname}) +endforeach() + + +ROOT_LINKER_LIBRARY(Minuit2TestMnSim MnSim/GaussDataGen.cxx MnSim/GaussFcn.cxx MnSim/GaussFcn2.cxx LIBRARIES Minuit2) + +#input text files +configure_file(MnSim/paul.txt paul.txt @COPY_ONLY) +configure_file(MnSim/paul2.txt paul2.txt @COPY_ONLY) +configure_file(MnSim/paul3.txt paul3.txt @COPY_ONLY) +configure_file(MnSim/paul4.txt paul4.txt @COPY_ONLY) + +foreach(file ${TestSourceMnSim}) + get_filename_component(testname ${file} NAME_WE) + ROOT_EXECUTABLE(${testname} ${file} LIBRARIES Minuit2 Minuit2TestMnSim) + ROOT_ADD_TEST(minuit2-${testname} COMMAND ${testname}) +endforeach() + +#for the global tests using ROOT libs (Minuit2 should be taken via the PluginManager) + +set(RootLibraries Core RIO Net Hist Graf Graf3d Gpad Tree + Rint Postscript Matrix Physics MathCore Thread) + +foreach(file ${TestSource}) + get_filename_component(testname ${file} NAME_WE) + ROOT_EXECUTABLE(${testname} ${file} LIBRARIES ${RootLibraries} ) + ROOT_ADD_TEST(minuit2-${testname} COMMAND ${testname}) +endforeach() + + diff --git a/math/cmaes/test/Makefile b/math/cmaes/test/Makefile new file mode 100644 index 0000000000000..077c535c41002 --- /dev/null +++ b/math/cmaes/test/Makefile @@ -0,0 +1,91 @@ +# Makefile for the ROOT test programs. +# This Makefile shows nicely how to compile and link applications +# using the ROOT libraries on all supported platforms. +# +# Copyright (c) 2000 Rene Brun and Fons Rademakers +# +# Author: Fons Rademakers, 29/2/2000 + +ROOTSYS = ../../.. +include $(ROOTSYS)/etc/Makefile.arch + +#------------------------------------------------------------------------------ + +ifeq ($(PLATFORM),win32) +EXTRALIBS = "$(ROOTSYS)/lib/libcmaesroot.lib" +else +EXTRALIBS = -lcmaesroot -lglog -lgflags +CXXFLAGS += -g -L/home/beniz/lib -L/usr/lib -L/usr/lib/x86_64-linux-gnu/ +endif + +# for using with MPI +ifneq ($(USE_MPI),) +CXX=mpic++ +LD=mpic++ +endif +ifneq ($(USE_OPENMP),) +CXXFLAGS += -D_GLIBCXX_PARALLEL -fopenmp +LDFLAGS += -fopenmp +endif + + + +USERFUNCOBJ = testUserFunc.$(ObjSuf) +USERFUNCSRC = testUserFunc.$(SrcSuf) +USERFUNC = testUserFunc$(ExeSuf) + +MINIMIZEROBJ = testMinimizer.$(ObjSuf) +MINIMIZERSRC = testMinimizer.$(SrcSuf) +MINIMIZER = testMinimizer$(ExeSuf) + +NDIMFITOBJ = testNdimFit.$(ObjSuf) +NDIMFITSRC = testNdimFit.$(SrcSuf) +NDIMFIT = testNdimFit$(ExeSuf) + +GAUSFITOBJ = testUnbinGausFit.$(ObjSuf) +GAUSFITSRC = testUnbinGausFit.$(SrcSuf) +GAUSFIT = testUnbinGausFit$(ExeSuf) + + +OBJS = $(USERFUNCOBJ) $(GRAPHOBJ) $(MINIMIZEROBJ) $(NDIMFITOBJ) $(GAUSFITOBJ) + +PROGRAMS = $(USERFUNC) $(GRAPH) $(MINIMIZER) $(NDIMFIT) $(GAUSFIT) + +.SUFFIXES: .$(SrcSuf) .$(ObjSuf) $(ExeSuf) + + +all: $(PROGRAMS) + +$(USERFUNC): $(USERFUNCOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(MINIMIZER): $(MINIMIZEROBJ) +ifeq ($(PLATFORM),win32) + $(LD) $(LDFLAGS) $^ $(LIBS) "$(ROOTSYS)/lib/libcmaesroot.lib" $(OutPutOpt)$@ +else + $(LD) $(LDFLAGS) $^ $(LIBS) -lMathCore $(OutPutOpt)$@ +endif + @echo "$@ done" + +$(NDIMFIT): $(NDIMFITOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(GAUSFIT): $(GAUSFITOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + + +clean: + @rm -f $(OBJS) core + +distclean: clean + @rm -f $(PROGRAMS) *Dict.* *.def *.exp \ + *.root *.ps *.so *.lib *.dll *.d .def so_locations + +.SUFFIXES: .$(SrcSuf) + + +.$(SrcSuf).$(ObjSuf): + $(CXX) $(CXXFLAGS) -c $< diff --git a/math/cmaes/test/testMinimizer.cxx b/math/cmaes/test/testMinimizer.cxx new file mode 100644 index 0000000000000..ace9ab6fd5830 --- /dev/null +++ b/math/cmaes/test/testMinimizer.cxx @@ -0,0 +1,891 @@ +// test of minimization using new minimizer classes + +#include "Math/Minimizer.h" +#include "Math/Factory.h" +#include "Math/Functor.h" + +#include "TVirtualFitter.h" +#include "TSystem.h" + +#include "Math/IFunction.h" +#include "Math/Util.h" +#include +#include + +#include +#include + +#include "TStopwatch.h" +#include "TMatrixD.h" +#include "TVectorD.h" +#include "TRandom3.h" +#include "TMath.h" + +//#define DEBUG + +int gNCall = 0; +int gNCall2 = 0; +int gNmin = 1000; +int gVerbose = 0; +bool useGradient = false; + +bool minos = true; + +double gAbsTolerance = 0.005; + +// Rosenbrok function to be minimize + +typedef void (*FCN)(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag); + + + +// ROSENBROCK function +//______________________________________________________________________________ +void RosenBrock(Int_t &, Double_t *, Double_t &f, Double_t *par, Int_t /*iflag*/) +{ + gNCall++; + const Double_t x = par[0]; + const Double_t y = par[1]; + const Double_t tmp1 = y-x*x; + const Double_t tmp2 = 1-x; + f = 100*tmp1*tmp1+tmp2*tmp2; +} + + + +class RosenBrockFunction : public ROOT::Math::IMultiGenFunction { + +public : + + virtual ~RosenBrockFunction() {} + + unsigned int NDim() const { return 2; } + + ROOT::Math::IMultiGenFunction * Clone() const { + return new RosenBrockFunction(); + } + + const double * TrueMinimum() const { + fTrueMin[0] = 1; + fTrueMin[1] = 1; + return fTrueMin; + } + + private: + + inline double DoEval (const double * x) const { +#ifdef USE_FREE_FUNC + double f = 0; + int ierr = 0; + int i = 0; + RosenBrock(i,0,f,const_cast(x),ierr); + return f; +#else + gNCall++; + const Double_t xx = x[0]; + const Double_t yy = x[1]; + const Double_t tmp1 = yy-xx*xx; + const Double_t tmp2 = 1-xx; + return 100*tmp1*tmp1+tmp2*tmp2; +#endif + } + + + mutable double fTrueMin[2]; +}; + + +// TRIGONOMETRIC FLETCHER FUNCTION + +class TrigoFletcherFunction : public ROOT::Math::IMultiGradFunction { + +public : + + + TrigoFletcherFunction(unsigned int dim) : fDim(dim) { + double seed = 3; + A.ResizeTo(dim,dim); + B.ResizeTo(dim,dim); + x0.ResizeTo(dim); + sx0.ResizeTo(dim); + cx0.ResizeTo(dim); + sx.ResizeTo(dim); + cx.ResizeTo(dim); + v0.ResizeTo(dim); + v.ResizeTo(dim); + r.ResizeTo(dim); + A.Randomize(-100.,100,seed); + B.Randomize(-100.,100,seed); + for (unsigned int i = 0; i < dim; i++) { + for (unsigned int j = 0; j < dim; j++) { + A(i,j) = int(A(i,j)); + B(i,j) = int(B(i,j)); + } + } + x0.Randomize(-TMath::Pi(),TMath::Pi(),seed); + // calculate vector Ei + for (unsigned int i = 0; i < fDim ; ++i) { + cx0[i] = std::cos(x0[i]); + sx0[i] = std::sin(x0[i]); + } + v0 = A*sx0+B*cx0; + } + + + unsigned int NDim() const { return fDim; } + + ROOT::Math::IMultiGenFunction * Clone() const { + TrigoFletcherFunction * f = new TrigoFletcherFunction(*this); +// std::cerr <<"cannot clone this function" << std::endl; +// assert(0); + return f; + } + + + void StartPoints(double * x, double * s) { + TRandom3 rndm; + const double stepSize = 0.01; + const double deltaAmp = 0.1; + const double pi = TMath::Pi(); + for (unsigned int i = 0; i < fDim; ++i) { + double delta = rndm.Uniform(-deltaAmp*pi,deltaAmp*pi); + x[i] = x0(i) + 0.1*delta; + if (x[i] <= - pi) x[i] += 2.*pi; + if (x[i] > pi) x[i] -= 2.*pi; + s[i] = stepSize; + } + } + + + const double * TrueMinimum() const { + return x0.GetMatrixArray(); + } + + + void Gradient (const double * x, double * g) const { + gNCall2++; + + for (unsigned int i = 0; i < fDim ; ++i) { + cx [i] = std::cos(x[i]); + sx [i] = std::sin(x[i]); + } + + v = A*sx +B*cx; + r = v0-v; + + + // calculate the grad components + for (unsigned int i = 0; i < fDim ; ++i) { + g[i] = 0; + for (unsigned int k = 0; k < fDim ; ++k) { + g[i] += 2. * r(k) * ( - A(k,i) * cx(i) + B(k,i) * sx(i) ); + } + } + + } + +#ifdef USE_FDF + void FdF (const double * x, double & f, double * g) const { + gNCall++; + + for (unsigned int i = 0; i < fDim ; ++i) { + cx [i] = std::cos(x[i]); + sx [i] = std::sin(x[i]); + } + + v = A*sx +B*cx; + r = v0-v; + + f = r * r; + + + // calculate the grad components + for (unsigned int i = 0; i < fDim ; ++i) { + g[i] = 0; + for (unsigned int k = 0; k < fDim ; ++k) { + g[i] += 2. * r(k) * ( - A(k,i) * cx(i) + B(k,i) * sx(i) ); + } + } + } +#endif + + private: + +// TrigoFletcherFunction(const TrigoFletcherFunction & ) {} +// TrigoFletcherFunction & operator=(const TrigoFletcherFunction &) { return *this; } + + double DoEval (const double * x) const { + gNCall++; + + + for (unsigned int i = 0; i < fDim ; ++i) { + cx [i] = std::cos(x[i]); + sx [i] = std::sin(x[i]); + } + + v = A*sx +B*cx; + r = v0-v; + + return r * r; + } + + + double DoDerivative (const double * x, unsigned int i ) const { + std::vector g(fDim); + Gradient(x,&g[0]); + return g[i]; + } + +private: + + unsigned int fDim; + + TMatrixD A; + TMatrixD B; + TVectorD x0; + mutable TVectorD sx0; + mutable TVectorD cx0; + mutable TVectorD sx; + mutable TVectorD cx; + mutable TVectorD v0; + mutable TVectorD v; + mutable TVectorD r; + + +}; + + +// CHEBYQUAD FUNCTION + +class ChebyQuadFunction : public ROOT::Math::IMultiGradFunction { + +public : + + ChebyQuadFunction(unsigned int n) : + fDim(n), + fvec(std::vector(n) ), + fTrueMin(std::vector(n) ) + { + } + + unsigned int NDim() const { return fDim; } + + ROOT::Math::IMultiGenFunction * Clone() const { + return new ChebyQuadFunction(*this); + } + + const double * TrueMinimum() const { + return &fTrueMin[0]; + } + + // use equally spaced points + void StartPoints(double * x, double * s) { + for (unsigned int i = 0; i < fDim; ++i) { + s[i] = 0.01; + x[i] = double(i)/(double(fDim)+1.0); + } + } + + // compute gradient + + void Gradient(const double * x, double * g) const { + gNCall2++; + unsigned int n = fDim; + // estimate first the fvec + DoCalculatefi(x); + + for (unsigned int j = 0; j < n; ++j) { + g[j] = 0.0; + double t1 = 1.0; + double t2 = 2.0 * x[j] - 1.0; + double t = 2.0 * t2; + double s1 = 0.0; + double s2 = 2.0; + for (unsigned int i = 0; i < n; ++i) { + g[j] += fvec[i] * s2; + double th = 4.0 * t2 + t * s2 - s1; + s1 = s2; + s2 = th; + th = t * t2 - t1; + t1 = t2; + t2 = th; + } + g[j] = 2. * g[j] / double(n); + } + + + } + + private: + + double DoEval (const double * x) const { + + gNCall++; + DoCalculatefi(x); + double f = 0; + for (unsigned int i = 0; i < fDim; ++i) + f += fvec[i] * fvec[i]; + + return f; + + } + + double DoDerivative (const double * x, unsigned int i ) const { + std::vector g(fDim); + Gradient(x,&g[0]); + return g[i]; + } + + void DoCalculatefi(const double * x) const { + // calculate the i- element ; F(X) = Sum {fi] + unsigned int n = fDim; + for (unsigned int i = 0; i < n; ++i) + fvec[i] = 0; + + for (unsigned int j = 0; j < n; ++j) { + double t1 = 1.0; + double t2 = 2.0 * x[j] - 1.0; + double t = 2.0 * t2; + for (unsigned int i = 0; i < n; ++i) { + fvec[i] += t2; + double th = t * t2 - t1; + t1 = t2; + t2 = th; + } + } + + // sum with the integral (integral is zero for odd Cheb polynomial and = 1/(i**2 -1) for the even ones + for (unsigned int i = 1; i <= n; ++i) { + int l = i-1; + fvec[l] /= double ( n ); + if ( ( i % 2 ) == 0 ) { + fvec[l] += 1.0 / ( double ( i*i ) - 1.0 ); + } + } + } + + unsigned int fDim; + mutable std::vector fvec; + mutable std::vector fTrueMin; +}; + +//WOOD function (4 dim function) + +double WoodFunction(const double * par) { + gNCall++; + + const double w = par[0]; + const double x = par[1]; + const double y = par[2]; + const double z = par[3]; + + const double w1 = w-1; + const double x1 = x-1; + const double y1 = y-1; + const double z1 = z-1; + const double tmp1 = x-w*w; + const double tmp2 = z-y*y; + + double f = 100*tmp1*tmp1+w1*w1+90*tmp2*tmp2+y1*y1+10.1*(x1*x1+z1*z1)+19.8*x1*z1; + return f; +} + +//Powell Function (4 dim function) +double PowellFunction(const double * par) { + gNCall++; + + const double w = par[0]; + const double x = par[1]; + const double y = par[2]; + const double z = par[3]; + + const double tmp1 = w+10*x; + const double tmp2 = y-z; + const double tmp3 = x-2*y; + const double tmp4 = w-z; + + double f = tmp1*tmp1+5*tmp2*tmp2+tmp3*tmp3*tmp3*tmp3+10*tmp4*tmp4*tmp4*tmp4; + return f; +} + +double SimpleQuadFunction(const double * par) { + gNCall++; + double x = par[0]; + double y = par[1]; + double f = x * x + 2 * y * y - x*y; + std::cout << "Quadfunc " << gNCall << "\t" << x << " , " << y << " f = " << f << std::endl; + return f; +} + +const double * TrueMinimum(const ROOT::Math::IMultiGenFunction & func) { + + const RosenBrockFunction * fRB = dynamic_cast< const RosenBrockFunction *> (&func); + if (fRB != 0) return fRB->TrueMinimum(); + const TrigoFletcherFunction * fTF = dynamic_cast< const TrigoFletcherFunction *> (&func); + if (fTF != 0) return fTF->TrueMinimum(); +// const ChebyQuadFunction * fCQ = dynamic_cast< const ChebyQuadFunction *> (&func); +// if (fCQ != 0) return fCQ->TrueMinimum(); + return 0; +} + +void printMinimum(const std::vector & x) { + std::cout << "Minimum X values\n"; + std::cout << "\t"; + int pr = std::cout.precision(12); + unsigned int n = x.size(); + for (unsigned int i = 0; i < n; ++i) { + std::cout << x[i]; + if ( i != n-1 ) std::cout << " , "; + if ( i > 0 && i % 6 == 0 ) std::cout << "\n\t"; + } + std::cout << std::endl; + std::cout.precision(pr); +} + +int DoNewMinimization( const ROOT::Math::IMultiGenFunction & func, const double * x0, const double * s0, ROOT::Math::Minimizer * min, double &minval, double &edm, double * minx) { + + int iret = 0; + + min->SetMaxFunctionCalls(1000000); + min->SetMaxIterations(100000); + min->SetTolerance(gAbsTolerance); + if (func.NDim() >= 10) { + min->SetTolerance(0.01); + + } + + min->SetPrintLevel(gVerbose); + // check if func provides gradient + const ROOT::Math::IMultiGradFunction * gfunc = dynamic_cast(&func); + if (gfunc != 0 && useGradient) + min->SetFunction(*gfunc); + else + min->SetFunction(func); + + for (unsigned int i = 0; i < func.NDim(); ++i) { +#ifdef DEBUG + std::cout << "set variable " << i << " to value " << x0[i] << std::endl; +#endif + min->SetVariable(i,"x" + ROOT::Math::Util::ToString(i),x0[i], s0[i]); + } + + bool ret = min->Minimize(); + minval = min->MinValue(); + edm = min->Edm(); + + if (!ret) { + return -1; + } + + const double * xmin = min->X(); + + bool ok = true; + const double * trueMin = TrueMinimum(func); + if (trueMin != 0) { + for (unsigned int i = 0; i < func.NDim(); ++i) + ok &= (std::fabs(xmin[i]-trueMin[i] ) < gAbsTolerance); + } + + if (!ok) iret = -2; + int ncall_migrad = gNCall; + + // test Minos (use the default up of 1) + if (minos) { + + double el,eu; + for (unsigned int i = 0; i < func.NDim(); ++i) { + ret = min->GetMinosError(i,el,eu); + std::cout << "ncalls " << gNCall << "\t"; + if (ret) std::cout << "MINOS error for " << i << " = " << el << " " << eu << std::endl; + else std::cout << "MINOS failed for " << i << std::endl; + } + } + + std::cout << "\nMigrad Ncalls:\t " << ncall_migrad << std::endl; + std::cout << "Minos Ncalls :\t " << gNCall - ncall_migrad << std::endl; + + +// std::cout << "function at the minimum " << func(xmin) << std::endl; + std::copy(xmin,xmin+func.NDim(),minx); + min->Clear(); + + return iret; +} + +int DoOldMinimization( FCN func, TVirtualFitter * min, double &minval, double &edm) { + + int iret = 0; + + assert(min != 0); + min->SetFCN( func ); + + Double_t arglist[100]; + arglist[0] = gVerbose-1; + min->ExecuteCommand("SET PRINT",arglist,1); + + min->SetParameter(0,"x",-1.2,0.01,0,0); + min->SetParameter(1,"y", 1.0,0.01,0,0); + + arglist[0] = 0; + min->ExecuteCommand("SET NOW",arglist,0); + arglist[0] = 1000; // number of function calls + arglist[1] = gAbsTolerance; // tolerance + //min->ExecuteCommand("MIGRAD",arglist,0); + min->ExecuteCommand("MIGRAD",arglist,2); + + if (minos) min->ExecuteCommand("MINOS",arglist,0); + + Double_t parx,pary; + Double_t we,al,bl; + Char_t parName[32]; + min->GetParameter(0,parName,parx,we,al,bl); + min->GetParameter(1,parName,pary,we,al,bl); + + bool ok = ( TMath::Abs(parx-1.) < gAbsTolerance && + TMath::Abs(pary-1.) < gAbsTolerance ); + + + double errdef = 0; + int nvpar, nparx; + min->GetStats(minval,edm,errdef,nvpar,nparx); + if (!ok) iret = -2; + + min->Clear(); // for further use + return iret; + +} + + +int testNewMinimizer( const ROOT::Math::IMultiGenFunction & func, const double * x0, const double * s0, const std::string & minimizer, const std::string & algoType) { + + std::cout << "\n************************************************************\n"; + std::cout << "\tTest new ROOT::Math::Minimizer\n"; + std::cout << "\tMinimizer is " << minimizer << " " << algoType << std::endl; + + int iret = 0; + double minval,edm = 0; + std::vector xmin(func.NDim() ); + + TStopwatch w; + w.Start(); + + ROOT::Math::Minimizer * min = ROOT::Math::Factory::CreateMinimizer(minimizer, algoType); + if (min == 0) { + std::cout << "Error using minimizer " << minimizer << " " << algoType << std::endl; + return -1; + } + + + for (int i = 0; i < gNmin; ++i) { + gNCall = 0; gNCall2 = 0; + iret |= DoNewMinimization(func, x0, s0, min,minval,edm,&xmin[0]); + } + + w.Stop(); + if (iret != 0) std::cout << "\n****** ERROR: Minimization FAILED ! \n"; + int pr = std::cout.precision(18); + std::cout << "\nNCalls: \t" << gNCall << " , " << gNCall2 + << "\tMinValue: \t" << minval << "\tEdm: \t" << edm; std::cout.precision(pr); + std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl; + printMinimum(xmin ); + std::cout << "\n************************************************************\n"; + +#ifdef CHECK_WITHMINUIT + // do Minuit after BFGS + if (minimizer == "GSL_BFGS") { + std::cout << "DO cmaes from last point\n"; + gNCall = 0; + iret |= DoNewMinimization(func, &xmin.front(), s0, "cmaes","",minval,edm,&xmin[0]); + int pr = std::cout.precision(18); + std::cout << "\nNCalls: \t" << gNCall << "\tMinValue: \t" << minval << "\tEdm: \t" << edm; std::cout.precision(pr); + std::cout << std::endl; + } +#endif + + delete min; + + return iret; +} + + +int testOldMinimizer( FCN func, const std::string & fitter, int n=25) { + + std::cout << "\n************************************************************\n"; + std::cout << "\tTest using TVirtualFitter\n"; + std::cout << "\tFitter is " << fitter << std::endl; + + int iret = 0; + double minval,edm = 0; + + TStopwatch w; + w.Start(); + + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + + TVirtualFitter *min = TVirtualFitter::Fitter(0,n); + + //min->Dump(); + + for (int i = 0; i < gNmin; ++i) { + gNCall = 0; + iret |= DoOldMinimization(func, min,minval,edm); + } + + w.Stop(); + if (iret != 0) std::cout << "\n****** ERROR: Minimization FAILED ! \n"; + int pr = std::cout.precision(18); + std::cout << "\nNCalls: \t" << gNCall << "\tMinValue: \t" << minval << "\tEdm: \t" << edm; std::cout.precision(pr); + std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl; + std::cout << "\n************************************************************\n"; + + return iret; +} + +int testRosenBrock() { + + int iret = 0; + + + std::cout << "\n************************************************************\n"; + std::cout << "\tROSENBROCK function test\n\n"; + + double s0[2] = {0.01,0.01}; + + // minimize using Rosenbrock Function +#ifndef DEBUG + gNmin = 2000; +#endif + + gNmin = 1; + + + RosenBrockFunction fRB; + double xRB[2] = { -1.,1.2}; + + iret |= testNewMinimizer(fRB,xRB,s0,"Minuit",""); + iret |= testNewMinimizer(fRB,xRB,s0,"cmaes",""); + +// iret |= testNewMinimizer(fRB,xRB,s0,"GSLMultiMin","ConjugateFR"); +// iret |= testNewMinimizer(fRB,xRB,s0,"GSLMultiMin","ConjugatePR"); +// iret |= testNewMinimizer(fRB,xRB,s0,"GSLMultiMin","BFGS"); +// iret |= testNewMinimizer(fRB,xRB,s0,"GSLMultiMin","BFGS2"); + +// iret |= testOldMinimizer(RosenBrock,"Minuit",2); +// iret |= testOldMinimizer(RosenBrock,"cmaes",2); + + + return iret; +} + + +int testChebyQuad() { + + int iret = 0; + + // test with ChebyQuad function + + const int n = 8; + ChebyQuadFunction func(n); + +#ifndef DEBUG + gNmin = std::max(1, int(20000/n/n) ); +#endif + gNmin = 1; + + + double s0[n]; + double x0[n]; + func.StartPoints(x0,s0); + + std::cout << "\n************************************************************\n"; + std::cout << "\tCHEBYQUAD function test , n = " << n << "\n\n"; + + +// double x[8] = {0.043153E+00, 0.193091E+00, 0.266329E+00, 0.500000E+00, +// 0.500000E+00, 0.733671E+00, 0.806910E+00, 0.956847E+00 }; +// double x[2] = {0.5, 0.5001}; +// std::cout << "FUNC " << func(x) << std::endl; + double x1[100] = { 0.00712780070646 , 0.0123441993113 , 0.0195428378255 , 0.0283679084192 , 0.0385291131289 , 0.0492202424892 , 0.0591277976178 , + 0.0689433195252 , 0.0791293590525 , 0.088794974369 , 0.0988949579193 , 0.108607151294 , 0.118571075831 , + 0.128605446238 , 0.137918291068 , 0.149177761352 , 0.156665324587 , 0.170851061982 , 0.174688134016 , + 0.192838903364 , 0.193078270803 , 0.209255377225 , 0.217740096779 , 0.225888518345 , 0.241031047421 , + 0.244253844041 , 0.257830449676 , 0.269467652526 , 0.274286498012 , 0.288877029988 , 0.297549406597 , + 0.304950954529 , 0.319230811642 , 0.326387092206 , 0.335229058731 , 0.349178359226 , 0.355905988048 , + 0.365197862755 , 0.379068092603 , 0.385826036925 , 0.394978252826 , 0.408974425717 , 0.415968185065 , + 0.424621041584 , 0.438837361714 , 0.446214149031 , 0.454242324351 , 0.468614308013 , 0.476506553416 , + 0.483916944941 , 0.498229247409 , 0.506794629616 , 0.513736742474 , 0.527712475478 , 0.537073277673 , + 0.543731917673 , 0.557187513963 , 0.567346279639 , 0.57379846397 , 0.586691058785 , 0.597561941009 , + 0.60382873461 , 0.616316037506 , 0.627719652101 , 0.633760038662 , 0.646175283836 , 0.657809344891 , + 0.663569004722 , 0.676314563639 , 0.687674566849 , 0.69332205923 , 0.706839545953 , 0.716907408637 , + 0.723407327715 , 0.738019389561 , 0.744806584048 , 0.754657613362 , 0.769181875619 , 0.772250323489 , + 0.787104833193 , 0.795856360905 , 0.804099304478 , 0.82142178741 , 0.819589601284 , 0.839024540481 , + 0.842457233039 , 0.857393475964 , 0.86408033345 , 0.876329840525 , 0.884867318008 , 0.895744532071 , + 0.905113958163 , 0.915445338697 , 0.925148068352 , 0.935344457785 , 0.945127838313 , 0.955272197168 , + 0.965687518559 , 0.975129521484 , 0.982662007764 }; + + std::cout << "FUNC " << func(x1) << std::endl; + + + iret |= testNewMinimizer(func,x0,s0, "Minuit",""); + iret |= testNewMinimizer(func,x0,s0, "cmaes",""); + +// iret |= testNewMinimizer(func,x0,s0, "GSLMultiMin","ConjugateFR"); +// iret |= testNewMinimizer(func,x0,s0, "GSLMultiMin","ConjugatePR"); +// iret |= testNewMinimizer(func,x0,s0, "GSLMultiMin","BFGS"); + + return iret; +} + + +int testTrigoFletcher() { + + int iret = 0; + + + // test with fletcher trigonometric function +#ifndef DEBUG + gNmin = 2; +#endif + gNmin = 1; + + const int nT = 50; + TrigoFletcherFunction fTrigo(nT); + double sTrigo[nT]; + double xTrigo[nT]; + fTrigo.StartPoints(xTrigo,sTrigo); + + std::cout << "\n************************************************************\n"; + std::cout << "\tTRIGONOMETRIC Fletcher function test , n = " << nT << "\n\n"; + + + iret |= testNewMinimizer(fTrigo,xTrigo,sTrigo,"cmaes",""); + iret |= testNewMinimizer(fTrigo,xTrigo,sTrigo,"Minuit",""); + +// iret |= testNewMinimizer(fTrigo,xTrigo,sTrigo,"GSLMultiMin","ConjugateFR"); +// iret |= testNewMinimizer(fTrigo,xTrigo,sTrigo,"GSLMultiMin","ConjugatePR"); +// iret |= testNewMinimizer(fTrigo,xTrigo,sTrigo,"GSLMultiMin","BFGS"); + + + return iret; +} + + +int testWood() { + + int iret = 0; + + + // test with Wood function (4d) +// minimum : F(1,1,1,1) = 0. + + +#ifndef DEBUG + gNmin = 1000; +#endif + gNmin = 1; + + ROOT::Math::Functor f(&WoodFunction,4); + + double x0[4] = { -3, -1, -3, -1 }; + double s0[4] = { 0.1, 0.1, 0.1, 0.1}; + + std::cout << "\n************************************************************\n"; + std::cout << "\tWOOD 4 function test \n\n"; + + + iret |= testNewMinimizer(f, x0, s0,"Minuit",""); + iret |= testNewMinimizer(f, x0, s0,"cmaes",""); + + + return iret; +} + +int testPowell() { + + int iret = 0; + + + // test with Powell function (4d) + // minimum is at F(0,0,0,0) = 0 +#ifndef DEBUG + gNmin = 1000; +#endif + gNmin = 1; + + ROOT::Math::Functor f(&PowellFunction,4); + + double x0[4] = { -3, -1, 0, 1 }; + double s0[4] = { 0.1, 0.1, 0.1, 0.1}; + + std::cout << "\n************************************************************\n"; + std::cout << "\tPOWELL function test \n\n"; + + + iret |= testNewMinimizer(f, x0, s0,"Minuit",""); + iret |= testNewMinimizer(f, x0, s0,"cmaes",""); + + + return iret; +} + + +int testQuadFunc() { + + int iret = 0; + + + // test with a simple quadratic function 2d + // minimum is at F(0,0) = 0 +#ifndef DEBUG + gNmin = 1000; +#endif + gNmin = 1; + + ROOT::Math::Functor f(&SimpleQuadFunction,2); + + double x0[4] = { -3, -3 }; + double s0[4] = { 0.1, 0.1}; + + std::cout << "\n************************************************************\n"; + std::cout << "\tSIMPLE QUAD function test \n\n"; + + + iret |= testNewMinimizer(f, x0, s0,"Minuit",""); + iret |= testNewMinimizer(f, x0, s0,"cmaes",""); + + + return iret; +} + + +int main() { + + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + + int iret = 0; + +#ifdef DEBUG + gVerbose = 4; + gNmin = 1; +#endif + + + iret |= testRosenBrock(); + iret |= testChebyQuad(); + iret |= testTrigoFletcher(); + + iret |= testWood(); + iret |= testPowell(); + + iret |= testQuadFunc(); + + + + if (iret != 0) + std::cerr << "testMinim :\t FAILED " << std::endl; + else + std::cerr << "testMinim :\t OK " << std::endl; + return iret; + +} diff --git a/math/cmaes/test/testNdimFit.cxx b/math/cmaes/test/testNdimFit.cxx new file mode 100644 index 0000000000000..b3cecc526f12d --- /dev/null +++ b/math/cmaes/test/testNdimFit.cxx @@ -0,0 +1,285 @@ +#include "TMath.h" +#include "TSystem.h" +#include "TRandom3.h" +#include "TTree.h" +#include "TROOT.h" + +#include "Fit/UnBinData.h" +#include "Fit/Fitter.h" + + +#include "Math/IParamFunction.h" +#include "Math/WrappedTF1.h" +#include "Math/WrappedMultiTF1.h" +#include "Math/WrappedParamFunction.h" +#include "Math/MultiDimParamFunctionAdapter.h" + +#include "TGraphErrors.h" + +#include "TStyle.h" + + +#include "Math/DistFunc.h" + +#include +#include + +#include "TStopwatch.h" + +#define DEBUG + +// test fit with many dimension + +const int N = 10; +const std::string branchType = "x[10]/D"; +const int NPoints = 100000; + +// const int N = 50; +// const std::string branchType = "x[50]/D"; +// const int NPoints = 10000; + + + +double truePar[2*N]; +double iniPar[2*N]; +//const int nfit = 1; +const int strategy = 0; + +double gausnorm(const double *x, const double *p) { + + double invsig = 1./p[1]; + double tmp = (x[0]-p[0]) * invsig; + const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 ); + return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig; +} + +double gausnormN(const double *x, const double *p) { + double f = 1; + for (int i = 0; i < N; ++i) + f *= gausnorm(x+i,p+2*i); + + return f; +} + +struct CMAES { + static std::string name() { return "cmaes"; } + static std::string name2() { return "acmaes"; } +}; + +// fill fit data structure +ROOT::Fit::UnBinData * FillUnBinData(TTree * tree ) { + + // fill the unbin data set from a TTree + ROOT::Fit::UnBinData * d = 0; + + // for the large tree access directly the branches + d = new ROOT::Fit::UnBinData(); + + unsigned int n = tree->GetEntries(); +#ifdef DEBUG + std::cout << "number of unbin data is " << n << " of dim " << N << std::endl; +#endif + d->Initialize(n,N); + TBranch * bx = tree->GetBranch("x"); + double vx[N]; + bx->SetAddress(vx); + std::vector m(N); + for (int unsigned i = 0; i < n; ++i) { + bx->GetEntry(i); + d->Add(vx); + for (int j = 0; j < N; ++j) + m[j] += vx[j]; + } + +#ifdef DEBUG + std::cout << "average values of means :\n"; + for (int j = 0; j < N; ++j) + std::cout << m[j]/n << " "; + std::cout << "\n"; +#endif + + delete tree; + tree = 0; + return d; + +} + + +// unbin fit + +typedef ROOT::Math::IParamMultiFunction Func; +template +int DoUnBinFit(T * tree, Func & func, bool debug = false ) { + + ROOT::Fit::UnBinData * d = FillUnBinData(tree ); + // need to have done Tree->Draw() before fit + //FillUnBinData(d,tree); + + //std::cout << "data size type and size is " << typeid(*d).name() << " " << d->Size() << std::endl; + std::cout << "Fit data size = " << d->Size() << " dimension = " << d->NDim() << std::endl; + + + + //printData(d); + + // create the fitter + //std::cout << "Fit parameter 2 " << f.Parameters()[2] << std::endl; + + ROOT::Fit::Fitter fitter; + fitter.Config().SetMinimizer(MinType::name().c_str(),MinType::name2().c_str()); + + if (debug) + fitter.Config().MinimizerOptions().SetPrintLevel(3); + else + fitter.Config().MinimizerOptions().SetPrintLevel(0); + + // set tolerance 1 for tree to be same as in TTTreePlayer::UnBinFIt + fitter.Config().MinimizerOptions().SetTolerance(1); + + // set strategy (0 to avoid MnHesse + fitter.Config().MinimizerOptions().SetStrategy(strategy); + + + // create the function + + fitter.SetFunction(func); + // need to fix param 0 , normalization in the unbinned fits + //fitter.Config().ParSettings(0).Fix(); + + bool ret = fitter.Fit(*d); + if (!ret) { + std::cout << " Fit Failed " << std::endl; + return -1; + } + if (debug) + fitter.Result().Print(std::cout); + + // check fit result + double chi2 = 0; + for (int i = 0; i < N; ++i) { + double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) ); + chi2 += d*d; + } + double prob = ROOT::Math::chisquared_cdf_c(chi2,N); + int iret = (prob < 1.0E-6) ? -1 : 0; + if (iret != 0) { + std::cout <<"Found difference in fitted values - prob = " << prob << std::endl; + if (!debug) fitter.Result().Print(std::cout); + for (int i = 0; i < N; ++i) { + double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) ); + std::cout << "par_" << i << " = " << fitter.Result().Value(i) << " true = " << truePar[i] << " pull = " << d << std::endl; + } + + } + + delete d; + + return iret; + +} + + +template +int DoFit(TTree * tree, Func & func, bool debug = false ) { + return DoUnBinFit(tree, func, debug); +} +// template +// int DoFit(TH1 * h1, Func & func, bool debug = false, bool copyData = false ) { +// return DoBinFit(h1, func, debug, copyData); +// } +// template +// int DoFit(TGraph * gr, Func & func, bool debug = false, bool copyData = false ) { +// return DoBinFit(gr, func, debug, copyData); +// } + +template +int FitUsingNewFitter(FitObj * fitobj, Func & func ) { + + std::cout << "\n************************************************************\n"; + std::cout << "\tFit using new Fit::Fitter " << typeid(*fitobj).name() << std::endl; + std::cout << "\tMinimizer is " << MinType::name() << " " << MinType::name2() << " func dim = " << func.NDim() << std::endl; + + int iret = 0; + TStopwatch w; w.Start(); + +#ifdef DEBUG + std::cout << "initial Parameters " << iniPar << " " << *iniPar << " " << *(iniPar+1) << std::endl; + func.SetParameters(iniPar); + iret |= DoFit(fitobj,func,true ); + +#else + for (int i = 0; i < nfit; ++i) { + func.SetParameters(iniPar); + iret = DoFit(fitobj,func, false); + if (iret != 0) { + std::cout << "Fit failed " << std::endl; + break; + } + } +#endif + w.Stop(); + std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl; + std::cout << "\n************************************************************\n"; + + return iret; +} + + +int testNdimFit() { + + + std::cout << "\n\n************************************************************\n"; + std::cout << "\t UNBINNED TREE (GAUSSIAN MULTI-DIM) FIT\n"; + std::cout << "************************************************************\n"; + + TTree * t1 = new TTree("t2","a large Tree with gaussian variables"); + double x[N]; + Int_t ev; + t1->Branch("x",x,branchType.c_str()); + t1->Branch("ev",&ev,"ev/I"); + + // generate the true parameters + for (int j = 0; j < N; ++j) { + double mu = double(j)/10.; + double s = 1.0 + double(j)/10.; + truePar[2*j] = mu; + truePar[2*j+1] = s; + } + + + //fill the tree + TRandom3 r; + for (Int_t i=0;iFill(); + + } + //t1.Draw("x"); // to select fit variable + + + for (int i = 0; i f2(&gausnormN,N,2*N,iniPar); + + int iret = 0; + iret |= FitUsingNewFitter(t1,f2); + + return iret; +} + +int main() { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + return testNdimFit(); +} diff --git a/math/cmaes/test/testUnbinGausFit.cxx b/math/cmaes/test/testUnbinGausFit.cxx new file mode 100644 index 0000000000000..9192ac50dc8fa --- /dev/null +++ b/math/cmaes/test/testUnbinGausFit.cxx @@ -0,0 +1,333 @@ +#include "TMath.h" +#include "TSystem.h" +#include "TRandom3.h" +#include "TTree.h" +#include "TROOT.h" + +#include "Fit/UnBinData.h" +#include "Fit/Fitter.h" + + +#include "Math/IParamFunction.h" +#include "Math/WrappedTF1.h" +#include "Math/WrappedMultiTF1.h" +#include "Math/WrappedParamFunction.h" +#include "Math/MultiDimParamFunctionAdapter.h" + +#include "TGraphErrors.h" + +#include "TStyle.h" + + +#include "Math/DistFunc.h" + +#include +#include + +#include "TStopwatch.h" + +#define DEBUG + +// test fit with many dimension + +const int N = 1; // 1d fit +const int NGaus = 3; +const int NPar = 8; // sum of 3 gaussians +const std::string branchType = "x[1]/D"; + +// for 8 core testing use 1M points +const int NPoints = 100000; +double truePar[NPar]; +double iniPar[NPar]; +//const int nfit = 1; +const int strategy = 0; + +double gausnorm(const double *x, const double *p) { + + double invsig = 1./std::abs(p[1]); + double tmp = (x[0]-p[0]) * invsig; + const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 ); + return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig; +} + +double gausSum(const double *x, const double *p) { + + double f = gausnorm(x,p+2) + + p[0] * gausnorm(x,p+4) + + p[1] * gausnorm(x,p+6); + + double norm = 1. + p[0] + p[1]; + return f/norm; +} + +struct CMAES { + static std::string name() { return "cmaes"; } + static std::string name2() { return "acmaes"; } +}; + +// fill fit data structure +ROOT::Fit::UnBinData * FillUnBinData(TTree * tree ) { + + // fill the unbin data set from a TTree + ROOT::Fit::UnBinData * d = 0; + + // for the large tree access directly the branches + d = new ROOT::Fit::UnBinData(); + + unsigned int n = tree->GetEntries(); +#ifdef DEBUG + std::cout << "number of unbin data is " << n << " of dim " << N << std::endl; +#endif + d->Initialize(n,N); + TBranch * bx = tree->GetBranch("x"); + double vx[N]; + bx->SetAddress(vx); + std::vector m(N); + for (int unsigned i = 0; i < n; ++i) { + bx->GetEntry(i); + d->Add(vx); + for (int j = 0; j < N; ++j) + m[j] += vx[j]; + } + +#ifdef DEBUG + std::cout << "average values of means :\n"; + for (int j = 0; j < N; ++j) + std::cout << m[j]/n << " "; + std::cout << "\n"; +#endif + + return d; +} + + +// unbin fit + +typedef ROOT::Math::IParamMultiFunction Func; +template +int DoUnBinFit(T * tree, Func & func, bool debug = false ) { + + ROOT::Fit::UnBinData * d = FillUnBinData(tree ); + // need to have done Tree->Draw() before fit + //FillUnBinData(d,tree); + + std::cout << "Filled the fit data " << std::endl; + //printData(d); + +#ifdef DEBUG + std::cout << "data size type and size is " << typeid(*d).name() << " " << d->Size() << std::endl; +#endif + + + + // create the fitter + //std::cout << "Fit parameter 2 " << f.Parameters()[2] << std::endl; + + ROOT::Fit::Fitter fitter; + fitter.Config().SetMinimizer(MinType::name().c_str(),MinType::name2().c_str()); + + if (debug) + fitter.Config().MinimizerOptions().SetPrintLevel(3); + else + fitter.Config().MinimizerOptions().SetPrintLevel(1); + + + // set tolerance 1 for tree to be same as in TTTreePlayer::UnBinFIt + fitter.Config().MinimizerOptions().SetTolerance(0.01); + + // set strategy (0 to avoid MnHesse + fitter.Config().MinimizerOptions().SetStrategy(strategy); + + + // create the function + + fitter.SetFunction(func); + // need to set limits to constant term + fitter.Config().ParSettings(0).SetLowerLimit(0.); + fitter.Config().ParSettings(1).SetLowerLimit(0.); + + if (debug) + std::cout << "do fitting... " << std::endl; + + bool ret = fitter.Fit(*d); + if (!ret) { + std::cout << " Fit Failed " << std::endl; + return -1; + } + if (debug) + fitter.Result().Print(std::cout); + + // check fit result + double chi2 = 0; + //if (fitter.Result().Value(0) < 0.5 ) { + for (int i = 0; i < NPar; ++i) { + double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) ); + chi2 += d*d; + } +//} +// else { +// double truePar2[NPar]; +// truePar2[0] = 1.-truePar[0]; +// truePar2[1] = truePar[3]; +// truePar2[2] = truePar[4]; +// truePar2[3] = truePar[1]; +// truePar2[4] = truePar[2]; +// for (int i = 0; i < N; ++i) { +// double d = ( truePar2[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) ); +// chi2 += d*d; +// } +// } + double prob = ROOT::Math::chisquared_cdf_c(chi2,NPar); + int iret = (prob < 1.0E-6) ? -1 : 0; + if (iret != 0) { + std::cout <<"Found difference in fitted values - chi2 = " << chi2 + << " prob = " << prob << std::endl; + fitter.Result().Print(std::cout); + } + + delete d; + + return iret; + +} + + +template +int DoFit(TTree * tree, Func & func, bool debug = false ) { + return DoUnBinFit(tree, func, debug); +} +// template +// int DoFit(TH1 * h1, Func & func, bool debug = false, bool copyData = false ) { +// return DoBinFit(h1, func, debug, copyData); +// } +// template +// int DoFit(TGraph * gr, Func & func, bool debug = false, bool copyData = false ) { +// return DoBinFit(gr, func, debug, copyData); +// } + +template +int FitUsingNewFitter(FitObj * fitobj, Func & func ) { + + std::cout << "\n************************************************************\n"; + std::cout << "\tFit using new Fit::Fitter " << typeid(*fitobj).name() << std::endl; + std::cout << "\tMinimizer is " << MinType::name() << " " << MinType::name2() << " func dim = " << func.NDim() << std::endl; + + int iret = 0; + TStopwatch w; w.Start(); + +#ifdef DEBUG + std::cout << "initial Parameters " << iniPar << " " << *iniPar << " " << *(iniPar+1) << std::endl; + func.SetParameters(iniPar); + iret |= DoFit(fitobj,func,true ); + if (iret != 0) { + std::cout << "Test failed " << std::endl; + } + +#else + for (int i = 0; i < nfit; ++i) { + func.SetParameters(iniPar); + iret = DoFit(fitobj,func, false); + if (iret != 0) { + std::cout << "Test failed " << std::endl; + break; + } + } +#endif + w.Stop(); + std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl; + std::cout << "\n************************************************************\n"; + + return iret; +} + + +int testNdimFit() { + + + std::cout << "\n\n************************************************************\n"; + std::cout << "\t UNBINNED TREE (GAUSSIAN MULTI-DIM) FIT\n"; + std::cout << "************************************************************\n"; + + TTree t1("t2","a large Tree with gaussian variables"); + double x[N]; + Int_t ev; + t1.Branch("x",x,branchType.c_str()); + t1.Branch("ev",&ev,"ev/I"); + + // generate the true parameters +// for (int j = 0; j < NGaus; ++j) { +// double a = j+1; +// double mu = double(j)/NGaus; +// double s = 1.0 + double(j)/NGaus; +// truePar[3*j] = a; +// truePar[3*j+1] = mu; +// truePar[3*j+2] = s; +// tot += a; +// } + truePar[0] = 0.2; // % second gaussian + truePar[1] = 0.05; // % third gaussian ampl + truePar[2] = 0.; // mean first gaussian + truePar[3] = 0.5; // s1 + truePar[4] = 0.; // mean secon gauss + truePar[5] = 1; + truePar[6] = -3; // mean third gaus + truePar[7] = 10; + + + + //fill the tree + TRandom3 r; + double norm = (1+truePar[0] + truePar[1] ); + double a = 1./norm; + double b = truePar[0]/ norm; + double c = truePar[1]/ norm; + assert(a+b+c == 1.); + std::cout << " True amplitude gaussians " << a << " " << b << " " << c << std::endl; + for (Int_t i=0;i f2(&gausSum,1,NPar,iniPar); + + int iret = 0; + iret |= FitUsingNewFitter(&t1,f2); + + return iret; +} + +int main() { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + return testNdimFit(); +} diff --git a/math/cmaes/test/testUserFunc.cxx b/math/cmaes/test/testUserFunc.cxx new file mode 100644 index 0000000000000..d175326201394 --- /dev/null +++ b/math/cmaes/test/testUserFunc.cxx @@ -0,0 +1,88 @@ +// @(#)root/minuit2:$Id$ +// Author: L. Moneta 10/2005 + +/********************************************************************** + * * + * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * + * * + **********************************************************************/ + + +#include "TApplication.h" +#include "TH1.h" +#include "TF1.h" +#include "TRandom3.h" +#include "Math/MinimizerOptions.h" +#include "TMath.h" +#include "TSystem.h" + +#include + +double myfunc( double * x, double * p) { + + return p[0]*TMath::Gaus(x[0],p[1],p[2]); +} + +void testUserFunc(std::string type="cmaes", int n = 1000) { + + + + gRandom = new TRandom3(); + + + ROOT::Math::MinimizerOptions::SetDefaultMinimizer(type.c_str() ); + + + + TH1D * h1 = new TH1D("h1","fit histo 1",100, -5, 5. ); + +// gStyle->SetOptStat(1111111); +// gStyle->SetOptFit(1111111); + + + + + for (int i = 0; i < n; ++i) { + h1->Fill( gRandom->Gaus(0,1) ); + } + + TF1 * f = new TF1("f",myfunc,-10,10,3); + double p[3] = { 100.0, 0.0, 1.0 } ; + f->SetParameters(p); + + h1->Fit(f); + // try fix a parameter + //TVirtualFitter * fitter = TVirtualFitter::GetFitter(); + //std::cout << typeid(*fitter).name() << std::endl; + //fitter->FixParameter(2); + f->FixParameter(2,1.0); + + h1->Fit(f,"V"); + + h1->Draw(); + + + +} + +#ifndef __CINT__ +int main(int argc, char **argv) +{ + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + if (argc > 1) { + TApplication theApp("App", &argc, argv); + testUserFunc( ); + theApp.Run(); + } + else + testUserFunc( ); + return 0; +} +#endif + +//#ifndef __CINT__ +//int main() { +// testUserFunc( ); +//} +//#endif From a9775a9d84d68565916c39f47172a80a3b01add3 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 26 May 2014 20:31:07 +0200 Subject: [PATCH 24/98] fixes and additions to current set of fit tutorials for CMA-ES + new tutorials --- tutorials/fit/cmaesFitBench.C | 6 +- tutorials/fit/cmaesFitBench2D.C | 14 +- tutorials/fit/cmaes_fit2a.C | 80 ++++++++++ tutorials/fit/cmaes_fit2dHist.C | 253 ++++++++++++++++++++++++++++++++ 4 files changed, 346 insertions(+), 7 deletions(-) create mode 100644 tutorials/fit/cmaes_fit2a.C create mode 100644 tutorials/fit/cmaes_fit2dHist.C diff --git a/tutorials/fit/cmaesFitBench.C b/tutorials/fit/cmaesFitBench.C index c462619932208..0878d09908a47 100644 --- a/tutorials/fit/cmaesFitBench.C +++ b/tutorials/fit/cmaesFitBench.C @@ -75,7 +75,7 @@ void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { histo->Fit(fitFcn,"Q0"); // from TH1.cxx: Q: quiet, 0: do not plot } - histo->Fit(fitFcn,"EV"); // E: use Minos, V: verbose. + histo->Fit(fitFcn,"V"); // E: use Minos, V: verbose. timer.Stop(); (histo->GetFunction("fitFcn"))->SetLineColor(kRed+3); @@ -120,9 +120,9 @@ void cmaesFitBench(Int_t npass=20) { c1->cd(3); DoFit("cmaes",gPad,npass); - //with sepcmaes + //with acmaes c1->cd(4); - DoFit("sepcmaes",gPad,npass); + DoFit("acmaes",gPad,npass); //c1->SaveAs("FitBench.root"); } diff --git a/tutorials/fit/cmaesFitBench2D.C b/tutorials/fit/cmaesFitBench2D.C index e6cc605afc656..f84a0d163db52 100644 --- a/tutorials/fit/cmaesFitBench2D.C +++ b/tutorials/fit/cmaesFitBench2D.C @@ -23,6 +23,8 @@ TF2 *fitFcn; TH2D *histo; +bool libloaded = false; + // Quadratic background function Double_t gaus2D(Double_t *x, Double_t *par) { double t1 = x[0] - par[1]; @@ -65,8 +67,12 @@ void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { } void cmaesFitBench2D(int n = 100000) { - gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); - gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + if (!libloaded) + { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + libloaded = true; + } TH1::AddDirectory(kFALSE); TCanvas *c1 = new TCanvas("c1","Fitting Demo",10,10,900,900); c1->Divide(2,2); @@ -93,7 +99,7 @@ void cmaesFitBench2D(int n = 100000) { c1->cd(1); DoFit("cmaes",gPad,npass); - //with sepcmaes + //with acmaes c1->cd(2); - DoFit("sepcmaes",gPad,npass); + DoFit("acmaes",gPad,npass); } diff --git a/tutorials/fit/cmaes_fit2a.C b/tutorials/fit/cmaes_fit2a.C new file mode 100644 index 0000000000000..9be4946f98095 --- /dev/null +++ b/tutorials/fit/cmaes_fit2a.C @@ -0,0 +1,80 @@ +#include "TF2.h" +#include "TH2.h" +#include "TCutG.h" +#include "TMath.h" +#include "TCanvas.h" +#include "TStyle.h" +#include "TVirtualFitter.h" + + +//+ Fitting a 2-D histogram (a variant) +// This tutorial illustrates : +// - how to create a 2-d function +// - fill a 2-d histogram randomly from this function +// - fit the histogram +// - display the fitted function on top of the histogram (lego-plot) +// using a surface plot in a sub-range of the histogram. +// +// This example can be executed via the interpreter or/and the compiler +// root > .x fit2a.C +// root > .x fit2a.C++ +//Author: Rene Brun +//Author: Emmanuel Benazera + +bool libloaded = false; + +Double_t g2(Double_t *x, Double_t *par) { + Double_t r1 = Double_t((x[0]-par[1])/par[2]); + Double_t r2 = Double_t((x[1]-par[3])/par[4]); + return par[0]*TMath::Exp(-0.5*(r1*r1+r2*r2)); +} +Double_t fun2(Double_t *x, Double_t *par) { + Double_t *p1 = &par[0]; + Double_t *p2 = &par[5]; + Double_t *p3 = &par[10]; + Double_t result = g2(x,p1) + g2(x,p2) + g2(x,p3); + return result; +} + +TCanvas *fit2a(const char *fitter="cmaes") { + if (!libloaded) + { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + libloaded = true; + } + + TVirtualFitter::SetDefaultFitter(fitter); + + TCanvas *c = new TCanvas(); + gStyle->SetOptStat(kTRUE); + gStyle->SetPalette(1); + const Int_t npar = 15; + Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + TF2 *f2 = new TF2("f2",fun2,-10,10,-10,10, npar); + f2->SetParameters(f2params); + + //Create an histogram and fill it randomly with f2 + TH2F *h2 = new TH2F("h2","From f2",40,-10,10,40,-10,10); + Int_t nentries = 100000; + h2->FillRandom("f2",nentries); + //Fit h2 with original function f2 + Float_t ratio = 4*nentries/100000; + f2params[ 0] *= ratio; + f2params[ 5] *= ratio; + f2params[10] *= ratio; + f2->SetParameters(f2params); + h2->Fit("f2","N"); + TCutG *cutg = new TCutG("cutg",5); + cutg->SetPoint(0,-7,-7); + cutg->SetPoint(1, 2,-7); + cutg->SetPoint(2, 2, 2); + cutg->SetPoint(3,-7, 2); + cutg->SetPoint(4,-7,-7); + h2->Draw("lego2 0"); + h2->SetFillColor(38); + f2->SetNpx(80); + f2->SetNpy(80); + f2->Draw("surf1 same bb [cutg]"); + return c; +} diff --git a/tutorials/fit/cmaes_fit2dHist.C b/tutorials/fit/cmaes_fit2dHist.C new file mode 100644 index 0000000000000..6b846c0820b77 --- /dev/null +++ b/tutorials/fit/cmaes_fit2dHist.C @@ -0,0 +1,253 @@ +// +//+ Example to fit two histograms at the same time via TVirtualFitter +// +// To execute this tutorial, you can do: +// +// root > .x fit2dHist.C (executing via CINT, slow) +// or +// root > .x fit2dHist.C+ (executing via ACLIC , fast, with Minuit) +// root > .x fit2dHist.C+(2) (executing via ACLIC , fast, with Minuit2) +// or using the option to fit independently the 2 histos +// root > .x fit2dHist.C+(10) (via ACLIC, fast, independent fits with Minuit) +// root > .x fit2dHist.C+(12) (via ACLIC, fast, independent fits with Minuit2) +// +// Note that you can also execute this script in batch with eg, +// root -b -q "fit2dHist.C+(12)" +// +// or execute interactively from the shell +// root fit2dHist.C+ +// root "fit2dHist.C+(12)" +// +// Authors: Lorenzo Moneta, Rene Brun 18/01/2006 + +#include "TH2D.h" +#include "TF2.h" +#include "TCanvas.h" +#include "TStyle.h" +#include "TRandom3.h" +#include "TVirtualFitter.h" +#include "TList.h" +#include "TSystem.h" + +#include + +bool libloaded = false; + +double gauss2D(double *x, double *par) { + double z1 = double((x[0]-par[1])/par[2]); + double z2 = double((x[1]-par[3])/par[4]); + return par[0]*exp(-0.5*(z1*z1+z2*z2)); +} +double my2Dfunc(double *x, double *par) { + return gauss2D(x,&par[0]) + gauss2D(x,&par[5]); +} + + +// data need to be globals to be visible by fcn +TRandom3 rndm; +TH2D *h1, *h2; +Int_t npfits; + +void myFcn(Int_t & /*nPar*/, Double_t * /*grad*/ , Double_t &fval, Double_t *p, Int_t /*iflag */ ) +{ + TAxis *xaxis1 = h1->GetXaxis(); + TAxis *yaxis1 = h1->GetYaxis(); + TAxis *xaxis2 = h2->GetXaxis(); + TAxis *yaxis2 = h2->GetYaxis(); + + int nbinX1 = h1->GetNbinsX(); + int nbinY1 = h1->GetNbinsY(); + int nbinX2 = h2->GetNbinsX(); + int nbinY2 = h2->GetNbinsY(); + + double chi2 = 0; + double x[2]; + double tmp; + npfits = 0; + for (int ix = 1; ix <= nbinX1; ++ix) { + x[0] = xaxis1->GetBinCenter(ix); + for (int iy = 1; iy <= nbinY1; ++iy) { + if ( h1->GetBinError(ix,iy) > 0 ) { + x[1] = yaxis1->GetBinCenter(iy); + tmp = (h1->GetBinContent(ix,iy) - my2Dfunc(x,p))/h1->GetBinError(ix,iy); + chi2 += tmp*tmp; + npfits++; + } + } + } + for (int ix = 1; ix <= nbinX2; ++ix) { + x[0] = xaxis2->GetBinCenter(ix); + for (int iy = 1; iy <= nbinY2; ++iy) { + if ( h2->GetBinError(ix,iy) > 0 ) { + x[1] = yaxis2->GetBinCenter(iy); + tmp = (h2->GetBinContent(ix,iy) - my2Dfunc(x,p))/h2->GetBinError(ix,iy); + chi2 += tmp*tmp; + npfits++; + } + } + } + fval = chi2; +} + +void FillHisto(TH2D * h, int n, double * p) { + + + const double mx1 = p[1]; + const double my1 = p[3]; + const double sx1 = p[2]; + const double sy1 = p[4]; + const double mx2 = p[6]; + const double my2 = p[8]; + const double sx2 = p[7]; + const double sy2 = p[9]; + //const double w1 = p[0]*sx1*sy1/(p[5]*sx2*sy2); + const double w1 = 0.5; + + double x, y; + for (int i = 0; i < n; ++i) { + // generate randoms with larger gaussians + rndm.Rannor(x,y); + + double r = rndm.Rndm(1); + if (r < w1) { + x = x*sx1 + mx1; + y = y*sy1 + my1; + } + else { + x = x*sx2 + mx2; + y = y*sy2 + my2; + } + h->Fill(x,y); + + } +} + + + + +int fit2dHist(int option=1) { + + if (!libloaded) + { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + libloaded = true; + } + + // create two histograms + + int nbx1 = 50; + int nby1 = 50; + int nbx2 = 50; + int nby2 = 50; + double xlow1 = 0.; + double ylow1 = 0.; + double xup1 = 10.; + double yup1 = 10.; + double xlow2 = 5.; + double ylow2 = 5.; + double xup2 = 20.; + double yup2 = 20.; + + h1 = new TH2D("h1","core",nbx1,xlow1,xup1,nby1,ylow1,yup1); + h2 = new TH2D("h2","tails",nbx2,xlow2,xup2,nby2,ylow2,yup2); + + double iniParams[10] = { 100, 6., 2., 7., 3, 100, 12., 3., 11., 2. }; + // create fit function + TF2 * func = new TF2("func",my2Dfunc,xlow2,xup2,ylow2,yup2, 10); + func->SetParameters(iniParams); + + // fill Histos + int n1 = 1000000; + int n2 = 1000000; + FillHisto(h1,n1,iniParams); + FillHisto(h2,n2,iniParams); + + // scale histograms to same heights (for fitting) + double dx1 = (xup1-xlow1)/double(nbx1); + double dy1 = (yup1-ylow1)/double(nby1); + double dx2 = (xup2-xlow2)/double(nbx2); + double dy2 = (yup2-ylow2)/double(nby2); + // scale histo 2 to scale of 1 + h2->Sumw2(); + h2->Scale( ( double(n1) * dx1 * dy1 ) / ( double(n2) * dx2 * dy2 ) ); + + bool global = false; + if (option > 10) global = true; + if (global) { + // fill data structure for fit (coordinates + values + errors) + std::cout << "Do global fit" << std::endl; + // fit now all the function together + + //The default minimizer is Minuit, you can also try Minuit2 + if (option%10 == 2) + TVirtualFitter::SetDefaultFitter("Minuit2"); + else TVirtualFitter::SetDefaultFitter("Minuit"); + TVirtualFitter * minuit = TVirtualFitter::Fitter(0,10); + for (int i = 0; i < 10; ++i) { + minuit->SetParameter(i, func->GetParName(i), func->GetParameter(i), 0.01, 0,0); + } + minuit->SetFCN(myFcn); + + double arglist[100]; + arglist[0] = 0; + // set print level + minuit->ExecuteCommand("SET PRINT",arglist,2); + + // minimize + arglist[0] = 5000; // number of function calls + arglist[1] = 0.01; // tolerance + minuit->ExecuteCommand("MIGRAD",arglist,2); + + //get result + double minParams[10]; + double parErrors[10]; + for (int i = 0; i < 10; ++i) { + minParams[i] = minuit->GetParameter(i); + parErrors[i] = minuit->GetParError(i); + } + double chi2, edm, errdef; + int nvpar, nparx; + minuit->GetStats(chi2,edm,errdef,nvpar,nparx); + + func->SetParameters(minParams); + func->SetParErrors(parErrors); + func->SetChisquare(chi2); + int ndf = npfits-nvpar; + func->SetNDF(ndf); + + // add to list of functions + h1->GetListOfFunctions()->Add(func); + h2->GetListOfFunctions()->Add(func); + } + else { + // fit independently + TVirtualFitter::SetDefaultFitter("ipop"); + h1->Fit(func); + h2->Fit(func); + } + + // Create a new canvas. + TCanvas * c1 = new TCanvas("c1","Two HIstogram Fit example",100,10,900,800); + c1->Divide(2,2); + gStyle->SetOptFit(); + gStyle->SetStatY(0.6); + + c1->cd(1); + h1->Draw(); + func->SetRange(xlow1,ylow1,xup1,yup1); + func->DrawCopy("cont1 same"); + c1->cd(2); + h1->Draw("lego"); + func->DrawCopy("surf1 same"); + c1->cd(3); + func->SetRange(xlow2,ylow2,xup2,yup2); + h2->Draw(); + func->DrawCopy("cont1 same"); + c1->cd(4); + h2->Draw("lego"); + gPad->SetLogz(); + func->Draw("surf1 same"); + + return 0; +} From 1c0d78049a920536477a729d2ad849250d52640f Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 27 May 2014 14:03:03 +0200 Subject: [PATCH 25/98] connected fUp to CMA-ES confidence interval (minos) computations --- math/cmaes/src/CMAESMinimizer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index af9a963a27db6..fffb7e99b1225 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -458,7 +458,7 @@ namespace ROOT if (!fWithBounds) { fCMAparams.set_automaxiter(true); - le = errstats<>::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize); + le = errstats<>::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize,fUp); } else { From 5d0b952e17ccac7c04c9ade29ee01868d0c3c7b4 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 27 May 2014 14:28:45 +0200 Subject: [PATCH 26/98] added control of max iterations and max functions eval to CMA-ES through wrapper --- math/cmaes/src/CMAESMinimizer.cxx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index fffb7e99b1225..e925d6921a7eb 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -330,10 +330,11 @@ namespace ROOT double sigma0 = *std::max_element(fInitialSigma.begin(),fInitialSigma.end()); int lambda = -1; - + int maxiter = fMaxIter > 0 ? fMaxIter : -1; + if (gDebug > 0) { - std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0 << " / lambda=" << lambda << " / fTol=" << fTol << " / with_bounds=" << fWithBounds << std::endl; + std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0 << " / lambda=" << lambda << " / fTol=" << fTol << " / with_bounds=" << fWithBounds << " / maxiter=" << maxiter << " / maxfevals=" << fMaxCalls << std::endl; std::cout << "x0="; std::copy(fInitialX.begin(),fInitialX.end(),std::ostream_iterator(std::cout," ")); std::cout << std::endl; @@ -353,6 +354,8 @@ namespace ROOT cmaparams.set_fixed_p((*mit).first,(*mit).second); cmaparams.set_ftolerance(fTol); cmaparams.set_automaxiter(false); + cmaparams.set_max_iter(maxiter); + cmaparams.set_max_fevals(fMaxCalls); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparamsb = cmaparams; } @@ -368,6 +371,8 @@ namespace ROOT cmaparams.set_fixed_p((*mit).first,(*mit).second); cmaparams.set_ftolerance(fTol); cmaparams.set_automaxiter(false); + cmaparams.set_max_iter(maxiter); + cmaparams.set_max_fevals(fMaxCalls); fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); fCMAparams = cmaparams; } From 0fc7f5e3b91ce00b96c3080089869d5db2ee3f6e Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 27 May 2014 14:38:46 +0200 Subject: [PATCH 27/98] did bump the default max function budget for CMA-ES --- math/cmaes/src/CMAESMinimizer.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index e925d6921a7eb..bfdb90bb8d7f4 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -331,10 +331,11 @@ namespace ROOT double sigma0 = *std::max_element(fInitialSigma.begin(),fInitialSigma.end()); int lambda = -1; int maxiter = fMaxIter > 0 ? fMaxIter : -1; + int maxfevals = 100*fMaxCalls; // CMA-ES requires much more calls than Minuit. if (gDebug > 0) { - std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0 << " / lambda=" << lambda << " / fTol=" << fTol << " / with_bounds=" << fWithBounds << " / maxiter=" << maxiter << " / maxfevals=" << fMaxCalls << std::endl; + std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0 << " / lambda=" << lambda << " / fTol=" << fTol << " / with_bounds=" << fWithBounds << " / maxiter=" << maxiter << " / maxfevals=" << maxfevals << std::endl; std::cout << "x0="; std::copy(fInitialX.begin(),fInitialX.end(),std::ostream_iterator(std::cout," ")); std::cout << std::endl; @@ -355,7 +356,7 @@ namespace ROOT cmaparams.set_ftolerance(fTol); cmaparams.set_automaxiter(false); cmaparams.set_max_iter(maxiter); - cmaparams.set_max_fevals(fMaxCalls); + cmaparams.set_max_fevals(maxfevals); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparamsb = cmaparams; } @@ -372,7 +373,7 @@ namespace ROOT cmaparams.set_ftolerance(fTol); cmaparams.set_automaxiter(false); cmaparams.set_max_iter(maxiter); - cmaparams.set_max_fevals(fMaxCalls); + cmaparams.set_max_fevals(maxfevals); fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); fCMAparams = cmaparams; } From 8d23ad19a746ebe4e2df8e78feff8fd577b307b6 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 16 Jun 2014 15:39:48 +0200 Subject: [PATCH 28/98] added support for MinimizerOptions with cmaes, fixes #4 --- math/cmaes/src/CMAESMinimizer.cxx | 41 ++++++++++++++++++++++++++++--- tutorials/fit/cmaes_fit2a.C | 4 +++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index bfdb90bb8d7f4..73c279249b2a1 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -35,6 +35,9 @@ using namespace libcmaes; namespace ROOT { + // registers a default empty set of extra options. + //ROOT::Math::IOptions &defIOptions = ROOT::Math::MinimizerOptions::Default("cmaes"); + namespace cmaes { @@ -67,6 +70,8 @@ namespace ROOT fMinimizer = sepIPOP_CMAES; else if (algoname == "sepbipop") fMinimizer = sepBIPOP_CMAES; + + } TCMAESMinimizer::TCMAESMinimizer(const TCMAESMinimizer &m) @@ -318,7 +323,10 @@ namespace ROOT MATH_WARN_MSG("TCMAESMinimizer::Minimize","Dimension smaller than initial X size's"); } - //ROOT::Math::IOptions *cmaesOpt = ROOT::Math::MinimizerOptions::FindDefault("cmaes"); //TODO. + ROOT::Math::IOptions *cmaesOpt = ROOT::Math::MinimizerOptions::FindDefault("cmaes"); + std::cerr << "cmaesOpt ptr: " << cmaesOpt << std::endl; + if (cmaesOpt) + cmaesOpt->Print(std::cout); //TODO: phenotype / genotype. @@ -327,11 +335,26 @@ namespace ROOT return (*fObjFunc)(x); }; + //TODO: gradient function. double sigma0 = *std::max_element(fInitialSigma.begin(),fInitialSigma.end()); int lambda = -1; int maxiter = fMaxIter > 0 ? fMaxIter : -1; int maxfevals = 100*fMaxCalls; // CMA-ES requires much more calls than Minuit. + int noisy = 0; + int nrestarts = -1; + double ftarget = -1.0; + std::string fplot; + + //TODO: set hyper-parameters according to IOptions object. + if (cmaesOpt) + { + cmaesOpt->GetValue("lambda",lambda); + cmaesOpt->GetValue("noisy",noisy); + cmaesOpt->GetValue("restarts",nrestarts); + cmaesOpt->GetValue("ftarget",ftarget); + cmaesOpt->GetValue("fplot",fplot); + } if (gDebug > 0) { @@ -354,9 +377,15 @@ namespace ROOT for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) cmaparams.set_fixed_p((*mit).first,(*mit).second); cmaparams.set_ftolerance(fTol); - cmaparams.set_automaxiter(false); cmaparams.set_max_iter(maxiter); cmaparams.set_max_fevals(maxfevals); + if (noisy > 0) + cmaparams.set_noisy(); + if (nrestarts > 0) + cmaparams.set_restarts(nrestarts); + if (ftarget > 0.0) + cmaparams.set_ftarget(ftarget); + cmaparams._fplot = fplot; fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparamsb = cmaparams; } @@ -371,9 +400,15 @@ namespace ROOT for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) cmaparams.set_fixed_p((*mit).first,(*mit).second); cmaparams.set_ftolerance(fTol); - cmaparams.set_automaxiter(false); cmaparams.set_max_iter(maxiter); cmaparams.set_max_fevals(maxfevals); + if (noisy > 0) + cmaparams.set_noisy(); + if (nrestarts > 0) + cmaparams.set_restarts(nrestarts); + if (ftarget > 0.0) + cmaparams.set_ftarget(ftarget); + cmaparams._fplot = fplot; fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); fCMAparams = cmaparams; } diff --git a/tutorials/fit/cmaes_fit2a.C b/tutorials/fit/cmaes_fit2a.C index 9be4946f98095..90cdc434e02a5 100644 --- a/tutorials/fit/cmaes_fit2a.C +++ b/tutorials/fit/cmaes_fit2a.C @@ -45,6 +45,10 @@ TCanvas *fit2a(const char *fitter="cmaes") { } TVirtualFitter::SetDefaultFitter(fitter); + + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); + //ROOT::Math::IOptions *opts = ROOT::Math::MinimizerOptions::FindDefault(fitter); + //opts.SetIntValue("lambda",100); TCanvas *c = new TCanvas(); gStyle->SetOptStat(kTRUE); From ad60a3c932d2887fb3b732fa1e95ea3a57fd3a0f Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 16 Jun 2014 15:40:59 +0200 Subject: [PATCH 29/98] using conservative min initial step-size value across all parameters for default cmaes initial value --- math/cmaes/src/CMAESMinimizer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 73c279249b2a1..edbc068ff0223 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -337,7 +337,7 @@ namespace ROOT //TODO: gradient function. - double sigma0 = *std::max_element(fInitialSigma.begin(),fInitialSigma.end()); + double sigma0 = *std::min_element(fInitialSigma.begin(),fInitialSigma.end()); int lambda = -1; int maxiter = fMaxIter > 0 ? fMaxIter : -1; int maxfevals = 100*fMaxCalls; // CMA-ES requires much more calls than Minuit. From fce8cacd846890bbb7eec95aaba5aea3395a56ae Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 16 Jun 2014 15:54:48 +0200 Subject: [PATCH 30/98] adapted tutorials to new cmaes performances --- tutorials/fit/cmaesFitBench.C | 3 +++ tutorials/fit/cmaes_fit2a.C | 1 + tutorials/fit/cmaes_fit2dHist.C | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tutorials/fit/cmaesFitBench.C b/tutorials/fit/cmaesFitBench.C index 0878d09908a47..c7cfb12c192f0 100644 --- a/tutorials/fit/cmaesFitBench.C +++ b/tutorials/fit/cmaesFitBench.C @@ -57,6 +57,9 @@ void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { // timer.Start(); TVirtualFitter::SetDefaultFitter(fitter); //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); + opts.SetIntValue("lambda",100); + pad->SetGrid(); pad->SetLogy(); fitFcn->SetParameters(1,1,1,6,.03,1); diff --git a/tutorials/fit/cmaes_fit2a.C b/tutorials/fit/cmaes_fit2a.C index 90cdc434e02a5..612893be4843e 100644 --- a/tutorials/fit/cmaes_fit2a.C +++ b/tutorials/fit/cmaes_fit2a.C @@ -49,6 +49,7 @@ TCanvas *fit2a(const char *fitter="cmaes") { ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); //ROOT::Math::IOptions *opts = ROOT::Math::MinimizerOptions::FindDefault(fitter); //opts.SetIntValue("lambda",100); + opts.SetNamedValue("fplot","fit2a.dat"); TCanvas *c = new TCanvas(); gStyle->SetOptStat(kTRUE); diff --git a/tutorials/fit/cmaes_fit2dHist.C b/tutorials/fit/cmaes_fit2dHist.C index 6b846c0820b77..c40683e579ea2 100644 --- a/tutorials/fit/cmaes_fit2dHist.C +++ b/tutorials/fit/cmaes_fit2dHist.C @@ -222,7 +222,7 @@ int fit2dHist(int option=1) { } else { // fit independently - TVirtualFitter::SetDefaultFitter("ipop"); + TVirtualFitter::SetDefaultFitter("cmaes"); h1->Fit(func); h2->Fit(func); } From c8bb5deefe34e9f58d0857f81a87532ad36882d0 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 16 Jun 2014 17:43:52 +0200 Subject: [PATCH 31/98] added support for gradient information with cmaes when available --- math/cmaes/inc/CMAESMinimizer.h | 4 +++- math/cmaes/src/CMAESMinimizer.cxx | 27 +++++++++++++++++++++++---- math/cmaes/test/testMinimizer.cxx | 2 +- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index ae02a3afad5f0..5b4614b78310f 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -76,7 +76,7 @@ namespace ROOT virtual void SetFunction(const ROOT::Math::IMultiGenFunction & func); /// set gradient the function to minimize - //virtual void SetFunction(const ROOT::Math::IMultiGradFunction & func); + virtual void SetFunction(const ROOT::Math::IMultiGradFunction & func); /// set free variable virtual bool SetVariable(unsigned int ivar, const std::string & name, double val, double step); @@ -295,6 +295,7 @@ namespace ROOT unsigned int fFreeDim = 0; // Number of free dimensions. int fMinimizer = CMAES_DEFAULT; // minimizer algo. const ROOT::Math::IMultiGenFunction *fObjFunc = nullptr; + const ROOT::Math::IMultiGradFunction *fObjFuncGrad = nullptr; std::vector fLBounds; // Lower bounds of variables std::vector fUBounds; // Upper bounds of variables std::vector fVariablesType; // 0 for free variable, 1 for fixed variable, 2 for lower bounded, 3 for upper bounded, 4 for lower and upper bounded. @@ -309,6 +310,7 @@ namespace ROOT mutable std::vector fValues; // X values. mutable std::vector fErrors; // X errors. bool fWithBounds = false; // whether using box-type constraints as required by parameters. + bool fWithGradient = false; // whether to use gradient information when available. }; } // end namespace cmaes diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index edbc068ff0223..23fe2b249d256 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -42,12 +42,12 @@ namespace ROOT { TCMAESMinimizer::TCMAESMinimizer() - :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false) + :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false),fWithGradient(false) { } TCMAESMinimizer::TCMAESMinimizer(const char *type) - :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false) + :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false),fWithGradient(false) { std::string algoname(type); // tolower() is not an std function (Windows) @@ -75,7 +75,7 @@ namespace ROOT } TCMAESMinimizer::TCMAESMinimizer(const TCMAESMinimizer &m) - :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false) + :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false),fWithGradient(false) { } @@ -110,6 +110,14 @@ namespace ROOT fObjFunc = &fun; fDim = fun.NDim(); } + + void TCMAESMinimizer::SetFunction(const ROOT::Math::IMultiGradFunction &fun) + { + SetFunction(static_cast (fun)); + fObjFuncGrad = &fun; + //fDim = fun.NDim(); + fWithGradient = true; + } bool TCMAESMinimizer::SetVariable(unsigned int ivar, const std::string & name, double val, double step) { @@ -335,7 +343,18 @@ namespace ROOT return (*fObjFunc)(x); }; - //TODO: gradient function. + // gradient function. + std::cout << "fWithGradient=" << fWithGradient << std::endl; + GradFunc gfit = nullptr; + if (fWithGradient) + { + gfit = [this](const double *x, const int N) + { + dVec grad(N); + fObjFuncGrad->Gradient(x,grad.data()); + return grad; + }; + } double sigma0 = *std::min_element(fInitialSigma.begin(),fInitialSigma.end()); int lambda = -1; diff --git a/math/cmaes/test/testMinimizer.cxx b/math/cmaes/test/testMinimizer.cxx index ace9ab6fd5830..dc42368a9dbff 100644 --- a/math/cmaes/test/testMinimizer.cxx +++ b/math/cmaes/test/testMinimizer.cxx @@ -27,7 +27,7 @@ int gNCall = 0; int gNCall2 = 0; int gNmin = 1000; int gVerbose = 0; -bool useGradient = false; +bool useGradient = true; bool minos = true; From fc4ffed954aa1c3839f73f9bd46b7a3f19905263 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 17 Jun 2014 17:20:19 +0200 Subject: [PATCH 32/98] added cmaes full bench tutorial script --- tutorials/fit/cmaesFullBench.C | 231 +++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 tutorials/fit/cmaesFullBench.C diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C new file mode 100644 index 0000000000000..521bf63b38518 --- /dev/null +++ b/tutorials/fit/cmaesFullBench.C @@ -0,0 +1,231 @@ +// Author: E. Benazera 6/2014 + +#include +#include +#include +#include + +#include "TH1.h" +#include "TF1.h" +#include "TStopwatch.h" +#include "TRandom3.h" +#include "TVirtualFitter.h" +#include "TPaveLabel.h" +#include "TStyle.h" +#include "TSystem.h" +#include "TFile.h" +#include "TMath.h" +#include "TROOT.h" + +class expstats +{ +public: + expstats() {} + ~expstats() {} + + void add_exp(const bool &succ, + const double &fmin, + const std::vector &x, + const double &cputime, + const double &budget) + { + if (succ) + ++_succs; + else ++_fails; + _fmin.push_back(fmin); + _x.push_back(x); + _cputime.push_back(cputime); + _cpu_avg = std::accumulate(_cputime.begin(),_cputime.end(),0.0) / static_cast(_cputime.size()); + _budget.push_back(budget); + _budget_avg = std::accumulate(_budget.begin(),_budget.end(),0.0) / static_cast(_budget.size()); + } + + expstats diff(const expstats &stats) + { + //TODO. + return expstats(); + } + + std::ostream& print(std::ostream &out) const + { + out << "succs=" << _succs << " / fails=" << _fails << " / cpu_avg=" << _cpu_avg << " / budget_avg=" << _budget_avg << std::endl; + return out; + } + + int _fails = 0; + int _succs = 0; + std::vector _fmin; + std::vector> _x; + std::vector _cputime; + double _cpu_avg = 0.0; + std::vector _budget; + double _budget_avg = 0.0; + + // diff + double _fdiff = 0; + double _cputime_diff = 0; + double _budget_diff = 0; + int _isuccs = 0; + int _ifails = 0; +}; + +std::ostream& operator<<(std::ostream &out, const expstats &stats) +{ + return stats.print(out); +} + +typedef std::function ExpFunc; + +ExpFunc experiment_gauss_fit = [](const std::string &fitter) +{ + int n = 1000; + gRandom = new TRandom3(); + TVirtualFitter::SetDefaultFitter(fitter.c_str() ); + std::string name = "h1_" + fitter; + TH1D * h1 = new TH1D(name.c_str(),"Chi2 Fit",100, -5, 5. ); + name = "h1bis_" + fitter; + TH1D * h1bis = new TH1D(name.c_str(),"Likelihood Fit",100, -5, 5. ); + for (int i = 0; i < n; ++i) { + double x = gRandom->Gaus(0,1); + h1->Fill( x ); + h1bis->Fill( x ); + } + TStopwatch timer; + timer.Start(); + TFitResultPtr r1 = h1->Fit("gaus","QS0"); + timer.Stop(); + Double_t cputime1 = timer.CpuTime(); + TStopwatch timer2; + timer2.Start(); + TFitResultPtr r2 = h1bis->Fit("gaus","QLES0"); + timer2.Stop(); + Double_t cputime2 = timer2.CpuTime(); + + expstats stats; + stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); + stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); + std::cout << "gaus_fit stats: " << stats << std::endl; + + return stats; +}; + +// Quadratic background function +Double_t background(Double_t *x, Double_t *par) { + return par[0] + par[1]*x[0] + par[2]*x[0]*x[0]; +} + +// Lorenzian Peak function +Double_t lorentzianPeak(Double_t *x, Double_t *par) { + return (0.5*par[0]*par[1]/TMath::Pi()) / + TMath::Max( 1.e-10,(x[0]-par[2])*(x[0]-par[2]) + .25*par[1]*par[1]); +} + +// Sum of background and peak function +Double_t fitFunction(Double_t *x, Double_t *par) { + return background(x,par) + lorentzianPeak(x,&par[3]); +} + +ExpFunc experiment_lorentz_fit = [](const std::string &fitter) +{ + expstats stats; + int npass = 20; + gRandom = new TRandom3(); + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetIntValue("lambda",100); + + TF1 *fitFcn = new TF1("fitFcn",fitFunction,0,3,6); + fitFcn->SetNpx(200); + fitFcn->SetParameters(1,1,1,6,.03,1); + fitFcn->Update(); + std::string title = fitter + " fit bench"; + TH1 *histo = new TH1D(fitter.c_str(),title.c_str(),200,0,3); + for (Int_t pass=0;passSetParameters(1,1,1,6,.03,1); + for (Int_t i=0;i<5000;i++) { + histo->Fill(fitFcn->GetRandom()); + } + //histo->Print("all"); + timer.Start(); + TFitResultPtr r = histo->Fit(fitFcn,"QS0"); // from TH1.cxx: Q: quiet, 0: do not plot + timer.Stop(); + Double_t cputime = timer.CpuTime(); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + } + TStopwatch timer; + timer.Start(); + TFitResultPtr r = histo->Fit(fitFcn,"QS0"); // E: use Minos + timer.Stop(); + double cputime = timer.CpuTime(); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),npass,timer.RealTime(),cputime); + delete fitFcn; + delete histo; + std::cout << "lorentz_fit stats: " << stats << std::endl; + return stats; +}; + +// Quadratic background function +Double_t gaus2D(Double_t *x, Double_t *par) { + double t1 = x[0] - par[1]; + double t2 = x[1] - par[2]; + return par[0]* exp( - 0.5 * ( t1*t1/( par[3]*par[3]) + t2*t2 /( par[4]*par[4] ) ) ) ; +} + +// Sum of background and peak function +Double_t fitFunction2(Double_t *x, Double_t *par) { + return gaus2D(x,par); +} + +void fillHisto(int n, + TH2D *histo) +{ + gRandom = new TRandom3(); + for (int i = 0; i < n; ++i) { + double x = gRandom->Gaus(2,3); + double y = gRandom->Gaus(-1,4); + histo->Fill(x,y,1.); + } +} + +ExpFunc experiment_gauss2D_fit = [](const std::string &fitter) +{ + int npass = 0; + int n = 100000; + TStopwatch timer; + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + TF2 *fitFcn = new TF2("fitFcn",fitFunction2,-10,10,-10,10,5); + fitFcn->SetParameters(100,0,0,2,7); + fitFcn->Update(); + TH2D *histo = new TH2D("h2","2D Gauss",100,-10,10,100,-10,10); + fillHisto(n,histo); + timer.Start(); + TFitResultPtr r = histo->Fit("fitFcn","S0"); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),npass,timer.RealTime(),cputime); + delete fitFcn; + delete histo; + expstats stats; + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + std::cout << "gauss2D_fit stats: " << stats << std::endl; + return stats; +}; + +void run_experiments() +{ + std::map mexperiments; + mexperiments.insert(std::pair("gauss_fit",experiment_gauss_fit)); + mexperiments.insert(std::pair("lorentz_fit",experiment_lorentz_fit)); + mexperiments.insert(std::pair("gauss2D_fit",experiment_gauss2D_fit)); + std::map::iterator mit = mexperiments.begin(); + while(mit!=mexperiments.end()) + { + (*mit).second("acmaes"); + ++mit; + } + +} From ff0c535e645b80428d99a9c6af7ad903d8c9138f Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Wed, 18 Jun 2014 12:07:53 +0200 Subject: [PATCH 33/98] added more examples + fixes to cmaes bench script --- tutorials/fit/cmaesFullBench.C | 320 +++++++++++++++++++++++++++++++-- 1 file changed, 306 insertions(+), 14 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 521bf63b38518..03a71beaf74a3 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -20,7 +20,8 @@ class expstats { public: - expstats() {} + expstats(const std::string &name): + _name(name) {} ~expstats() {} void add_exp(const bool &succ, @@ -40,18 +41,48 @@ public: _budget_avg = std::accumulate(_budget.begin(),_budget.end(),0.0) / static_cast(_budget.size()); } - expstats diff(const expstats &stats) + void diff(const expstats &stats) { - //TODO. - return expstats(); + if (_fmin.size() != stats._fmin.size()) + { + std::cout << "Error: diff requires same size sets\n"; + return; + } + for (size_t i=0;i<_fmin.size();i++) + { + double fdiff = _fmin.at(i)-stats._fmin.at(i); + double ffdiff = fabs(fdiff); + // should compare to tolerance but unable to access it. + if (ffdiff < 1e-2 || fdiff < 0.0) // ftol appears to default to 0.01 + ++_found; + if (fdiff <= 0.0) + ++_isuccs; + else ++_ifails; + _fdiff.push_back(fdiff); + _cputime_diff.push_back(_cputime.at(i)-stats._cputime.at(i)); + _budget_diff.push_back(_budget.at(i)-stats._budget.at(i)); + } + _cputime_diff_avg = std::accumulate(_cputime_diff.begin(),_cputime_diff.end(),0.0) / static_cast(_cputime_diff.size()); + _budget_diff_avg = std::accumulate(_budget_diff.begin(),_budget_diff.end(),0.0) / static_cast(_budget_diff.size()); } std::ostream& print(std::ostream &out) const { - out << "succs=" << _succs << " / fails=" << _fails << " / cpu_avg=" << _cpu_avg << " / budget_avg=" << _budget_avg << std::endl; + out << _name << " / succs=" << _succs << " / fails=" << _fails << " / cpu_avg=" << _cpu_avg << " / budget_avg=" << _budget_avg << std::endl; return out; } - + + std::ostream& print_diff(std::ostream &out) const + { + out << _name << " / found=" << _found << "/" << _fdiff.size() << " / isuccs=" << _isuccs << " / ifails=" << _ifails << " / cpu_diff_avg=" << _cputime_diff_avg << " / budget_diff_avg=" << _budget_diff_avg << std::endl; + for (size_t i=0;i<_fdiff.size();i++) + { + out << "#" << i << " - " << _name << ": " << "fdiff=" << _fdiff.at(i) << " / cputime_diff=" << _cputime_diff.at(i) << " / budget_diff=" << _budget_diff.at(i) << std::endl; + } + return out; + } + + std::string _name; int _fails = 0; int _succs = 0; std::vector _fmin; @@ -62,9 +93,12 @@ public: double _budget_avg = 0.0; // diff - double _fdiff = 0; - double _cputime_diff = 0; - double _budget_diff = 0; + int _found = 0; + std::vector _fdiff; + std::vector _cputime_diff; + std::vector _budget_diff; + double _cputime_diff_avg = 0.0; + double _budget_diff_avg = 0.0; int _isuccs = 0; int _ifails = 0; }; @@ -78,6 +112,7 @@ typedef std::function ExpFunc; ExpFunc experiment_gauss_fit = [](const std::string &fitter) { + std::string ename = "gauss_fit"; int n = 1000; gRandom = new TRandom3(); TVirtualFitter::SetDefaultFitter(fitter.c_str() ); @@ -101,7 +136,7 @@ ExpFunc experiment_gauss_fit = [](const std::string &fitter) timer2.Stop(); Double_t cputime2 = timer2.CpuTime(); - expstats stats; + expstats stats(ename); stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); std::cout << "gaus_fit stats: " << stats << std::endl; @@ -127,13 +162,14 @@ Double_t fitFunction(Double_t *x, Double_t *par) { ExpFunc experiment_lorentz_fit = [](const std::string &fitter) { - expstats stats; + std::string ename = "lorentz_fit"; + expstats stats(ename); int npass = 20; gRandom = new TRandom3(); TVirtualFitter::SetDefaultFitter(fitter.c_str()); //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); - opts.SetIntValue("lambda",100); + opts.SetIntValue("lambda",500); TF1 *fitFcn = new TF1("fitFcn",fitFunction,0,3,6); fitFcn->SetNpx(200); @@ -159,6 +195,7 @@ ExpFunc experiment_lorentz_fit = [](const std::string &fitter) timer.Start(); TFitResultPtr r = histo->Fit(fitFcn,"QS0"); // E: use Minos timer.Stop(); + opts.SetIntValue("lambda",-1); double cputime = timer.CpuTime(); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),npass,timer.RealTime(),cputime); @@ -193,6 +230,7 @@ void fillHisto(int n, ExpFunc experiment_gauss2D_fit = [](const std::string &fitter) { + std::string ename = "gauss2D_fit"; int npass = 0; int n = 100000; TStopwatch timer; @@ -209,23 +247,277 @@ ExpFunc experiment_gauss2D_fit = [](const std::string &fitter) printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),npass,timer.RealTime(),cputime); delete fitFcn; delete histo; - expstats stats; + expstats stats(ename); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); std::cout << "gauss2D_fit stats: " << stats << std::endl; return stats; }; +Double_t g2(Double_t *x, Double_t *par) { + Double_t r1 = Double_t((x[0]-par[1])/par[2]); + Double_t r2 = Double_t((x[1]-par[3])/par[4]); + return par[0]*TMath::Exp(-0.5*(r1*r1+r2*r2)); +} +Double_t fun2(Double_t *x, Double_t *par) { + Double_t *p1 = &par[0]; + Double_t *p2 = &par[5]; + Double_t *p3 = &par[10]; + Double_t result = g2(x,p1) + g2(x,p2) + g2(x,p3); + return result; +} + +ExpFunc experiment_fit2a = [](const std::string &fitter) +{ + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + + //ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); + //ROOT::Math::IOptions *opts = ROOT::Math::MinimizerOptions::FindDefault(fitter); + //opts.SetIntValue("lambda",100); + //opts.SetNamedValue("fplot","fit2a.dat"); + + const Int_t npar = 15; + Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + TF2 *f2 = new TF2("f2",fun2,-10,10,-10,10, npar); + f2->SetParameters(f2params); + + //Create an histogram and fill it randomly with f2 + TH2F *h2 = new TH2F("h2","From f2",40,-10,10,40,-10,10); + Int_t nentries = 100000; + h2->FillRandom("f2",nentries); + //Fit h2 with original function f2 + Float_t ratio = 4*nentries/100000; + f2params[ 0] *= ratio; + f2params[ 5] *= ratio; + f2params[10] *= ratio; + f2->SetParameters(f2params); + TStopwatch timer; + timer.Start(); + TFitResultPtr r = h2->Fit("f2","SN0"); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + delete f2; + delete h2; + expstats stats("fit2a"); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + return stats; +}; + +double gauss2D(double *x, double *par) { + double z1 = double((x[0]-par[1])/par[2]); + double z2 = double((x[1]-par[3])/par[4]); + return par[0]*exp(-0.5*(z1*z1+z2*z2)); +} +double my2Dfunc(double *x, double *par) { + return gauss2D(x,&par[0]) + gauss2D(x,&par[5]); +} + +void fit2D(Int_t & nPar, Double_t * grad , Double_t &fval, Double_t *p, Int_t iflag, + TH2D *h1, TH2D *h2) +{ + TAxis *xaxis1 = h1->GetXaxis(); + TAxis *yaxis1 = h1->GetYaxis(); + TAxis *xaxis2 = h2->GetXaxis(); + TAxis *yaxis2 = h2->GetYaxis(); + + int nbinX1 = h1->GetNbinsX(); + int nbinY1 = h1->GetNbinsY(); + int nbinX2 = h2->GetNbinsX(); + int nbinY2 = h2->GetNbinsY(); + + double chi2 = 0; + double x[2]; + double tmp; + Int_t npfits = 0; + for (int ix = 1; ix <= nbinX1; ++ix) { + x[0] = xaxis1->GetBinCenter(ix); + for (int iy = 1; iy <= nbinY1; ++iy) { + if ( h1->GetBinError(ix,iy) > 0 ) { + x[1] = yaxis1->GetBinCenter(iy); + tmp = (h1->GetBinContent(ix,iy) - my2Dfunc(x,p))/h1->GetBinError(ix,iy); + chi2 += tmp*tmp; + npfits++; + } + } + } + for (int ix = 1; ix <= nbinX2; ++ix) { + x[0] = xaxis2->GetBinCenter(ix); + for (int iy = 1; iy <= nbinY2; ++iy) { + if ( h2->GetBinError(ix,iy) > 0 ) { + x[1] = yaxis2->GetBinCenter(iy); + tmp = (h2->GetBinContent(ix,iy) - my2Dfunc(x,p))/h2->GetBinError(ix,iy); + chi2 += tmp*tmp; + npfits++; + } + } + } + fval = chi2; +} + +void FillHisto2(TH2D * h, int n, double * p) +{ + const double mx1 = p[1]; + const double my1 = p[3]; + const double sx1 = p[2]; + const double sy1 = p[4]; + const double mx2 = p[6]; + const double my2 = p[8]; + const double sx2 = p[7]; + const double sy2 = p[9]; + //const double w1 = p[0]*sx1*sy1/(p[5]*sx2*sy2); + const double w1 = 0.5; + TRandom3 rndm; + + double x, y; + for (int i = 0; i < n; ++i) { + // generate randoms with larger gaussians + rndm.Rannor(x,y); + + double r = rndm.Rndm(1); + if (r < w1) { + x = x*sx1 + mx1; + y = y*sy1 + my1; + } + else { + x = x*sx2 + mx2; + y = y*sy2 + my2; + } + h->Fill(x,y); + } +} + +ExpFunc experiment_fit2dhist = [](const std::string &fitter) +{ + expstats stats("fit2dhist"); + int nbx1 = 50; + int nby1 = 50; + int nbx2 = 50; + int nby2 = 50; + double xlow1 = 0.; + double ylow1 = 0.; + double xup1 = 10.; + double yup1 = 10.; + double xlow2 = 5.; + double ylow2 = 5.; + double xup2 = 20.; + double yup2 = 20.; + + TH2D *h1 = new TH2D("h1","core",nbx1,xlow1,xup1,nby1,ylow1,yup1); + TH2D *h2 = new TH2D("h2","tails",nbx2,xlow2,xup2,nby2,ylow2,yup2); + + double iniParams[10] = { 100, 6., 2., 7., 3, 100, 12., 3., 11., 2. }; + // create fit function + TF2 * func = new TF2("func",my2Dfunc,xlow2,xup2,ylow2,yup2, 10); + func->SetParameters(iniParams); + + // fill Histos + int n1 = 1000000; + int n2 = 1000000; + FillHisto2(h1,n1,iniParams); + FillHisto2(h2,n2,iniParams); + + // scale histograms to same heights (for fitting) + double dx1 = (xup1-xlow1)/double(nbx1); + double dy1 = (yup1-ylow1)/double(nby1); + double dx2 = (xup2-xlow2)/double(nbx2); + double dy2 = (yup2-ylow2)/double(nby2); + // scale histo 2 to scale of 1 + h2->Sumw2(); + h2->Scale( ( double(n1) * dx1 * dy1 ) / ( double(n2) * dx2 * dy2 ) ); + + /*bool global = false; + if (option > 10) global = true; + if (global) { + // fill data structure for fit (coordinates + values + errors) + std::cout << "Do global fit" << std::endl; + // fit now all the function together + + //The default minimizer + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + TVirtualFitter *vfit = TVirtualFitter::Fitter(0,10); + for (int i = 0; i < 10; ++i) { + vfit->SetParameter(i, func->GetParName(i), func->GetParameter(i), 0.01, 0,0); + } + vfit->SetFCN(fit2D); + + double arglist[100]; + arglist[0] = 0; + // set print level + vfit->ExecuteCommand("SET PRINT",arglist,2); + + // minimize + arglist[0] = 5000; // number of function calls + arglist[1] = 0.01; // tolerance + vfit->ExecuteCommand("MIGRAD",arglist,2); //TODO. + + //get result + double minParams[10]; + double parErrors[10]; + for (int i = 0; i < 10; ++i) { + minParams[i] = vfit->GetParameter(i); + parErrors[i] = vfit->GetParError(i); + } + double chi2, edm, errdef; + int nvpar, nparx; + vfit->GetStats(chi2,edm,errdef,nvpar,nparx); + + func->SetParameters(minParams); + func->SetParErrors(parErrors); + func->SetChisquare(chi2); + int ndf = npfits-nvpar; // beware: npfits global. + func->SetNDF(ndf); + + // add to list of functions + h1->GetListOfFunctions()->Add(func); + h2->GetListOfFunctions()->Add(func); + }*/ + //else { + // fit independently + TStopwatch timer; + timer.Start(); + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + TFitResultPtr r1 = h1->Fit(func,"S0"); + timer.Stop(); + Double_t cputime1 = timer.CpuTime(); + TStopwatch timer2; + timer2.Start(); + TFitResultPtr r2 = h2->Fit(func,"S0"); + timer2.Stop(); + Double_t cputime2 = timer2.CpuTime(); + + stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); + stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); + + //} + + delete h1; + delete h2; + + + return stats; + }; + void run_experiments() { + std::vector acmaes_stats; + std::vector minuit2_stats; std::map mexperiments; mexperiments.insert(std::pair("gauss_fit",experiment_gauss_fit)); mexperiments.insert(std::pair("lorentz_fit",experiment_lorentz_fit)); mexperiments.insert(std::pair("gauss2D_fit",experiment_gauss2D_fit)); + mexperiments.insert(std::pair("fit2a",experiment_fit2a)); + mexperiments.insert(std::pair("fit2dhist",experiment_fit2dhist)); std::map::iterator mit = mexperiments.begin(); while(mit!=mexperiments.end()) { - (*mit).second("acmaes"); + acmaes_stats.push_back((*mit).second("acmaes")); + minuit2_stats.push_back((*mit).second("Minuit2")); ++mit; } + + for (size_t i=0;i Date: Wed, 18 Jun 2014 12:16:51 +0200 Subject: [PATCH 34/98] added support for cmaes / minuit2 budget and cpu ratio to benchmark --- tutorials/fit/cmaesFullBench.C | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 03a71beaf74a3..c089eb27c9a90 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -60,10 +60,14 @@ public: else ++_ifails; _fdiff.push_back(fdiff); _cputime_diff.push_back(_cputime.at(i)-stats._cputime.at(i)); + _cputime_ratio.push_back(_cputime.at(i)/stats._cputime.at(i)); _budget_diff.push_back(_budget.at(i)-stats._budget.at(i)); + _budget_ratio.push_back(_budget.at(i)/stats._budget.at(i)); } _cputime_diff_avg = std::accumulate(_cputime_diff.begin(),_cputime_diff.end(),0.0) / static_cast(_cputime_diff.size()); + _cputime_ratio_avg = std::accumulate(_cputime_ratio.begin(),_cputime_ratio.end(),0.0) / static_cast(_cputime_ratio.size()); _budget_diff_avg = std::accumulate(_budget_diff.begin(),_budget_diff.end(),0.0) / static_cast(_budget_diff.size()); + _budget_ratio_avg = std::accumulate(_budget_ratio.begin(),_budget_ratio.end(),0.0) / static_cast(_budget_ratio.size()); } std::ostream& print(std::ostream &out) const @@ -74,10 +78,10 @@ public: std::ostream& print_diff(std::ostream &out) const { - out << _name << " / found=" << _found << "/" << _fdiff.size() << " / isuccs=" << _isuccs << " / ifails=" << _ifails << " / cpu_diff_avg=" << _cputime_diff_avg << " / budget_diff_avg=" << _budget_diff_avg << std::endl; + out << _name << " / found=" << _found << "/" << _fdiff.size() << " / isuccs=" << _isuccs << " / ifails=" << _ifails << " / cpu_diff_avg=" << _cputime_diff_avg << " / cpu_ratio_avg=" << _cputime_ratio_avg << " / budget_diff_avg=" << _budget_diff_avg << " / budget_ratio_avg=" << _budget_ratio_avg << std::endl; for (size_t i=0;i<_fdiff.size();i++) { - out << "#" << i << " - " << _name << ": " << "fdiff=" << _fdiff.at(i) << " / cputime_diff=" << _cputime_diff.at(i) << " / budget_diff=" << _budget_diff.at(i) << std::endl; + out << "#" << i << " - " << _name << ": " << "fdiff=" << _fdiff.at(i) << " / cputime_diff=" << _cputime_diff.at(i) << " / cputime_ratio=" << _cputime_ratio.at(i) << " / budget_diff=" << _budget_diff.at(i) << " / budget_ratio=" << _budget_ratio.at(i) << std::endl; } return out; } @@ -96,9 +100,13 @@ public: int _found = 0; std::vector _fdiff; std::vector _cputime_diff; + std::vector _cputime_ratio; std::vector _budget_diff; + std::vector _budget_ratio; double _cputime_diff_avg = 0.0; + double _cputime_ratio_avg = 1.0; double _budget_diff_avg = 0.0; + double _budget_ratio_avg = 1.0; int _isuccs = 0; int _ifails = 0; }; From 9a3ccedbaa79a79e44ea61b08fd731559c961c18 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Wed, 18 Jun 2014 13:46:33 +0200 Subject: [PATCH 35/98] fixed settings of fixed variables in cmaes minimizer --- math/cmaes/inc/CMAESMinimizer.h | 2 +- math/cmaes/src/CMAESMinimizer.cxx | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 5b4614b78310f..b5f37ed1aae37 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -102,7 +102,7 @@ namespace ROOT /// set the limits of an already existing variable virtual bool SetVariableLimits(unsigned int ivar, double lower, double upper); /// fix an existing variable - //virtual bool FixVariable(unsigned int ivar); + virtual bool FixVariable(unsigned int ivar); /// release an existing variable //virtual bool ReleaseVariable(unsigned int ivar); /// query if an existing variable is fixed (i.e. considered constant in the minimization) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 23fe2b249d256..2dcdf1ac5d732 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -211,6 +211,7 @@ namespace ROOT bool TCMAESMinimizer::SetFixedVariable(unsigned int ivar, const std::string &name, double val) { + SetVariable(ivar,name,val,0.0); fFixedVariables.insert(std::pair(ivar,val)); } @@ -280,6 +281,11 @@ namespace ROOT return true; } + bool TCMAESMinimizer::FixVariable(unsigned int ivar) + { + fFixedVariables.insert(std::pair(ivar,fInitialX.at(ivar))); // XXX: sets initial variable. + } + bool TCMAESMinimizer::GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const { if (ivar >= fInitialX.size()) @@ -332,7 +338,7 @@ namespace ROOT } ROOT::Math::IOptions *cmaesOpt = ROOT::Math::MinimizerOptions::FindDefault("cmaes"); - std::cerr << "cmaesOpt ptr: " << cmaesOpt << std::endl; + //std::cerr << "cmaesOpt ptr: " << cmaesOpt << std::endl; if (cmaesOpt) cmaesOpt->Print(std::cout); From 3acc44ce3f46e8baa09ebaaefee5febe614249d0 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Thu, 19 Jun 2014 08:41:00 +0200 Subject: [PATCH 36/98] fixed clearing of parameter object in cmaes wrapper --- math/cmaes/src/CMAESMinimizer.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 2dcdf1ac5d732..c458159de2090 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -92,6 +92,7 @@ namespace ROOT void TCMAESMinimizer::Clear() { fCMAsols = CMASolutions(); + fCMAparams = CMAParameters<>(); fDim = 0; fFreeDim = 0; fLBounds.clear(); fUBounds.clear(); From b694568e330ce1c73889a734978a28359cbd24bb Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Thu, 19 Jun 2014 10:52:40 +0200 Subject: [PATCH 37/98] new scheme in cmaes benchmark in order to compare algorithms on exact same random datasets --- tutorials/fit/cmaesFullBench.C | 575 ++++++++++++++++++++++++--------- 1 file changed, 421 insertions(+), 154 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index c089eb27c9a90..27d6e6f7f7d26 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -7,6 +7,8 @@ #include "TH1.h" #include "TF1.h" +#include "TH2D.h" +#include "TF2.h" #include "TStopwatch.h" #include "TRandom3.h" #include "TVirtualFitter.h" @@ -14,6 +16,7 @@ #include "TStyle.h" #include "TSystem.h" #include "TFile.h" +#include "TList.h" #include "TMath.h" #include "TROOT.h" @@ -118,57 +121,174 @@ std::ostream& operator<<(std::ostream &out, const expstats &stats) typedef std::function ExpFunc; -ExpFunc experiment_gauss_fit = [](const std::string &fitter) +class experiment { - std::string ename = "gauss_fit"; - int n = 1000; - gRandom = new TRandom3(); - TVirtualFitter::SetDefaultFitter(fitter.c_str() ); - std::string name = "h1_" + fitter; - TH1D * h1 = new TH1D(name.c_str(),"Chi2 Fit",100, -5, 5. ); - name = "h1bis_" + fitter; - TH1D * h1bis = new TH1D(name.c_str(),"Likelihood Fit",100, -5, 5. ); - for (int i = 0; i < n; ++i) { - double x = gRandom->Gaus(0,1); - h1->Fill( x ); - h1bis->Fill( x ); - } - TStopwatch timer; - timer.Start(); - TFitResultPtr r1 = h1->Fit("gaus","QS0"); - timer.Stop(); - Double_t cputime1 = timer.CpuTime(); - TStopwatch timer2; - timer2.Start(); - TFitResultPtr r2 = h1bis->Fit("gaus","QLES0"); - timer2.Stop(); - Double_t cputime2 = timer2.CpuTime(); +public: + experiment(const std::string &name) + :_name(name) + {} + + virtual ~experiment() {} + + virtual void Setup() {} + + virtual void Cleanup() {} - expstats stats(ename); - stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); - stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); - std::cout << "gaus_fit stats: " << stats << std::endl; + ExpFunc _ef; + std::string _name; +}; - return stats; +/*- gauss_fit -*/ +class gauss_fit_e : public experiment +{ +public: + gauss_fit_e() + :experiment("gauss_fit") + { + _ef = [this](const std::string &fitter) + { + std::string ename = "gauss_fit"; + + TVirtualFitter::SetDefaultFitter(fitter.c_str() ); + std::string name = "h1_" + fitter; + TH1D * h1 = new TH1D(name.c_str(),"Chi2 Fit",100, -5, 5. ); + name = "h1bis_" + fitter; + TH1D * h1bis = new TH1D(name.c_str(),"Likelihood Fit",100, -5, 5. ); + for (int i = 0; i < _n; ++i) { + h1->Fill( _x.at(i) ); + h1bis->Fill( _x.at(i) ); + } + TStopwatch timer; + timer.Start(); + TFitResultPtr r1 = h1->Fit("gaus","QS0"); + timer.Stop(); + Double_t cputime1 = timer.CpuTime(); + TStopwatch timer2; + timer2.Start(); + TFitResultPtr r2 = h1bis->Fit("gaus","QLES0"); + timer2.Stop(); + Double_t cputime2 = timer2.CpuTime(); + + delete h1; + delete h1bis; + + expstats stats(ename); + stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); + stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); + std::cout << "gaus_fit stats: " << stats << std::endl; + + return stats; + }; + } + + ~gauss_fit_e() {} + + virtual void Setup() + { + std::cout << "setting up gauss_fit\n"; + for (int i=0;i<_n;i++) + _x.push_back(_grandom.Gaus(0,1)); + } + + int _n = 1000; + TRandom3 _grandom; + std::vector _x; }; +gauss_fit_e ggauss_fit; -// Quadratic background function -Double_t background(Double_t *x, Double_t *par) { - return par[0] + par[1]*x[0] + par[2]*x[0]*x[0]; -} +/*- lorentz_fit -*/ +class lorentz_fit_e : public experiment +{ +public: + lorentz_fit_e() + :experiment("lorentz_fit") + { + _fitFcn = new TF1("fitFcn",lorentz_fit_e::fitFunction,0,3,6); + _ef = [this](const std::string &fitter) + { + std::string ename = "lorentz_fit"; + expstats stats(ename); + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); + + for (Int_t pass=0;pass<_npass;pass++) { + TStopwatch timer; + //histos.at(i)->Print("all"); + _fitFcn->SetParameters(1,1,1,6,.03,1); + timer.Start(); + TFitResultPtr r = _histos.at(pass)->Fit(_fitFcn,"QS0"); // from TH1.cxx: Q: quiet, 0: do not plot + timer.Stop(); + Double_t cputime = timer.CpuTime(); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + } + TStopwatch timer; + timer.Start(); + TFitResultPtr r = _histos.back()->Fit(_fitFcn,"QS0"); // E: use Minos + timer.Stop(); + double cputime = timer.CpuTime(); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),_npass,timer.RealTime(),cputime); + std::cout << "lorentz_fit stats: " << stats << std::endl; + return stats; + }; + } -// Lorenzian Peak function -Double_t lorentzianPeak(Double_t *x, Double_t *par) { - return (0.5*par[0]*par[1]/TMath::Pi()) / - TMath::Max( 1.e-10,(x[0]-par[2])*(x[0]-par[2]) + .25*par[1]*par[1]); -} + virtual ~lorentz_fit_e() + { + delete _fitFcn; + for (int i=0;i<_npass;i++) + delete _histos.at(i); + _histos.clear(); + } + + // Quadratic background function + static Double_t background(Double_t *x, Double_t *par) { + return par[0] + par[1]*x[0] + par[2]*x[0]*x[0]; + } -// Sum of background and peak function -Double_t fitFunction(Double_t *x, Double_t *par) { - return background(x,par) + lorentzianPeak(x,&par[3]); -} + // Lorenzian Peak function + static Double_t lorentzianPeak(Double_t *x, Double_t *par) { + return (0.5*par[0]*par[1]/TMath::Pi()) / + TMath::Max( 1.e-10,(x[0]-par[2])*(x[0]-par[2]) + .25*par[1]*par[1]); + } + + // Sum of background and peak function + static Double_t fitFunction(Double_t *x, Double_t *par) { + return lorentz_fit_e::background(x,par) + lorentz_fit_e::lorentzianPeak(x,&par[3]); + } -ExpFunc experiment_lorentz_fit = [](const std::string &fitter) + virtual void Setup() + { + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetIntValue("lambda",500); + _fitFcn->SetNpx(200); + _fitFcn->SetParameters(1,1,1,6,.03,1); + _fitFcn->Update(); + std::string title = "fit bench"; + TH1D *histo = new TH1D("fit",title.c_str(),200,0,3); + for (int i=0;i<_npass;i++) + { + histo->Fill(_fitFcn->GetRandom()); + _histos.push_back(new TH1D(*histo)); + } + } + + virtual void Cleanup() + { + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetIntValue("lambda",-1); + for (int i=0;i<_npass;i++) + delete _histos.at(i); + _histos.clear(); + } + + int _npass = 20; + TF1 *_fitFcn; + std::vector _histos; +}; +lorentz_fit_e glorentz_fit; + +/*ExpFunc experiment_lorentz_fit = [](const std::string &fitter) { std::string ename = "lorentz_fit"; expstats stats(ename); @@ -211,7 +331,7 @@ ExpFunc experiment_lorentz_fit = [](const std::string &fitter) delete histo; std::cout << "lorentz_fit stats: " << stats << std::endl; return stats; -}; + };*/ // Quadratic background function Double_t gaus2D(Double_t *x, Double_t *par) { @@ -319,48 +439,6 @@ double my2Dfunc(double *x, double *par) { return gauss2D(x,&par[0]) + gauss2D(x,&par[5]); } -void fit2D(Int_t & nPar, Double_t * grad , Double_t &fval, Double_t *p, Int_t iflag, - TH2D *h1, TH2D *h2) -{ - TAxis *xaxis1 = h1->GetXaxis(); - TAxis *yaxis1 = h1->GetYaxis(); - TAxis *xaxis2 = h2->GetXaxis(); - TAxis *yaxis2 = h2->GetYaxis(); - - int nbinX1 = h1->GetNbinsX(); - int nbinY1 = h1->GetNbinsY(); - int nbinX2 = h2->GetNbinsX(); - int nbinY2 = h2->GetNbinsY(); - - double chi2 = 0; - double x[2]; - double tmp; - Int_t npfits = 0; - for (int ix = 1; ix <= nbinX1; ++ix) { - x[0] = xaxis1->GetBinCenter(ix); - for (int iy = 1; iy <= nbinY1; ++iy) { - if ( h1->GetBinError(ix,iy) > 0 ) { - x[1] = yaxis1->GetBinCenter(iy); - tmp = (h1->GetBinContent(ix,iy) - my2Dfunc(x,p))/h1->GetBinError(ix,iy); - chi2 += tmp*tmp; - npfits++; - } - } - } - for (int ix = 1; ix <= nbinX2; ++ix) { - x[0] = xaxis2->GetBinCenter(ix); - for (int iy = 1; iy <= nbinY2; ++iy) { - if ( h2->GetBinError(ix,iy) > 0 ) { - x[1] = yaxis2->GetBinCenter(iy); - tmp = (h2->GetBinContent(ix,iy) - my2Dfunc(x,p))/h2->GetBinError(ix,iy); - chi2 += tmp*tmp; - npfits++; - } - } - } - fval = chi2; -} - void FillHisto2(TH2D * h, int n, double * p) { const double mx1 = p[1]; @@ -393,7 +471,7 @@ void FillHisto2(TH2D * h, int n, double * p) } } -ExpFunc experiment_fit2dhist = [](const std::string &fitter) +ExpFunc experiment_fit2dhist_indep = [](const std::string &fitter) { expstats stats("fit2dhist"); int nbx1 = 50; @@ -432,54 +510,6 @@ ExpFunc experiment_fit2dhist = [](const std::string &fitter) h2->Sumw2(); h2->Scale( ( double(n1) * dx1 * dy1 ) / ( double(n2) * dx2 * dy2 ) ); - /*bool global = false; - if (option > 10) global = true; - if (global) { - // fill data structure for fit (coordinates + values + errors) - std::cout << "Do global fit" << std::endl; - // fit now all the function together - - //The default minimizer - TVirtualFitter::SetDefaultFitter(fitter.c_str()); - TVirtualFitter *vfit = TVirtualFitter::Fitter(0,10); - for (int i = 0; i < 10; ++i) { - vfit->SetParameter(i, func->GetParName(i), func->GetParameter(i), 0.01, 0,0); - } - vfit->SetFCN(fit2D); - - double arglist[100]; - arglist[0] = 0; - // set print level - vfit->ExecuteCommand("SET PRINT",arglist,2); - - // minimize - arglist[0] = 5000; // number of function calls - arglist[1] = 0.01; // tolerance - vfit->ExecuteCommand("MIGRAD",arglist,2); //TODO. - - //get result - double minParams[10]; - double parErrors[10]; - for (int i = 0; i < 10; ++i) { - minParams[i] = vfit->GetParameter(i); - parErrors[i] = vfit->GetParError(i); - } - double chi2, edm, errdef; - int nvpar, nparx; - vfit->GetStats(chi2,edm,errdef,nvpar,nparx); - - func->SetParameters(minParams); - func->SetParErrors(parErrors); - func->SetChisquare(chi2); - int ndf = npfits-nvpar; // beware: npfits global. - func->SetNDF(ndf); - - // add to list of functions - h1->GetListOfFunctions()->Add(func); - h2->GetListOfFunctions()->Add(func); - }*/ - //else { - // fit independently TStopwatch timer; timer.Start(); TVirtualFitter::SetDefaultFitter(fitter.c_str()); @@ -494,38 +524,275 @@ ExpFunc experiment_fit2dhist = [](const std::string &fitter) stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); - - //} - delete h1; delete h2; + return stats; +}; + +// definition of shared parameter +// background function +int iparB[2] = { 0, // exp amplitude in B histo + 2 // exp common parameter +}; + +// signal + background function +int iparSB[5] = { 1, // exp amplitude in S+B histo + 2, // exp common parameter + 3, // gaussian amplitude + 4, // gaussian mean + 5 // gaussian sigma +}; + +struct GlobalChi2 { + GlobalChi2( ROOT::Math::IMultiGenFunction & f1, + ROOT::Math::IMultiGenFunction & f2) : + fChi2_1(&f1), fChi2_2(&f2) {} + + // parameter vector is first background (in common 1 and 2) + // and then is signal (only in 2) + double operator() (const double *par) const { + double p1[2]; + for (int i = 0; i < 2; ++i) p1[i] = par[iparB[i] ]; + + double p2[5]; + for (int i = 0; i < 5; ++i) p2[i] = par[iparSB[i] ]; + + return (*fChi2_1)(p1) + (*fChi2_2)(p2); + } + + const ROOT::Math::IMultiGenFunction * fChi2_1; + const ROOT::Math::IMultiGenFunction * fChi2_2; +}; + +ExpFunc experiment_combined = [](const std::string &fitter) +{ + expstats stats("combined"); + + TH1D * hB = new TH1D("hB","histo B",100,0,100); + TH1D * hSB = new TH1D("hSB","histo S+B",100, 0,100); + + TF1 * fB = new TF1("fB","expo",0,100); + fB->SetParameters(1,-0.05); + hB->FillRandom("fB"); + + TF1 * fS = new TF1("fS","gaus",0,100); + fS->SetParameters(1,30,5); + hSB->FillRandom("fB",2000); + hSB->FillRandom("fS",1000); + + // perform now global fit - return stats; - }; + TF1 * fSB = new TF1("fSB","expo + gaus(2)",0,100); + + ROOT::Math::WrappedMultiTF1 wfB(*fB,1); + ROOT::Math::WrappedMultiTF1 wfSB(*fSB,1); + + ROOT::Fit::DataOptions opt; + ROOT::Fit::DataRange rangeB; + // set the data range + rangeB.SetRange(10,90); + ROOT::Fit::BinData dataB(opt,rangeB); + ROOT::Fit::FillData(dataB, hB); + + ROOT::Fit::DataRange rangeSB; + rangeSB.SetRange(10,50); + ROOT::Fit::BinData dataSB(opt,rangeSB); + ROOT::Fit::FillData(dataSB, hSB); + + ROOT::Fit::Chi2Function chi2_B(dataB, wfB); + ROOT::Fit::Chi2Function chi2_SB(dataSB, wfSB); + + GlobalChi2 globalChi2(chi2_B, chi2_SB); + + ROOT::Fit::Fitter rfitter; + + const int Npar = 6; + double par0[Npar] = { 5,5,-0.1,100, 30,10}; + + // create before the parameter settings in order to fix or set range on them + rfitter.Config().SetParamsSettings(6,par0); + // fix 5-th parameter + rfitter.Config().ParSettings(4).Fix(); + // set limits on the third and 4-th parameter + rfitter.Config().ParSettings(2).SetLimits(-10,-1.E-4); + rfitter.Config().ParSettings(3).SetLimits(0,10000); + rfitter.Config().ParSettings(3).SetStepSize(5); + + rfitter.Config().MinimizerOptions().SetPrintLevel(0); + if (fitter == "Minuit2") + rfitter.Config().SetMinimizer("Minuit2","Migrad"); + else if (fitter.find("cmaes")!=std::string::npos) + rfitter.Config().SetMinimizer("cmaes","acmaes"); + + // fit FCN function directly + // (specify optionally data size and flag to indicate that is a chi2 fit) + TStopwatch timer; + timer.Start(); + rfitter.FitFCN(6,globalChi2,0,dataB.Size()+dataSB.Size(),true); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + ROOT::Fit::FitResult r = rfitter.Result(); + //result.Print(std::cout); + + delete hB; + delete hSB; + delete fB; + delete fS; + delete fSB; + + stats.add_exp(r.Status()==0,r.MinFcnValue(),r.Parameters(),cputime,r.NCalls()); + return stats; +}; + +ExpFunc experiment_example3D = [](const std::string &fitter) +{ + expstats stats("example3D"); + const int n = 1000; + double x[n], y[n], z[n], v[n]; + double ev = 0.1; + + // generate the data + TRandom2 r; + for (int i = 0; i < n; ++i) { + x[i] = r.Uniform(0,10); + y[i] = r.Uniform(0,10); + z[i] = r.Uniform(0,10); + v[i] = sin(x[i] ) + cos(y[i]) + z[i] + r.Gaus(0,ev); + } + + // create a 3d binned data structure + ROOT::Fit::BinData data(n,3); + double xx[3]; + for(int i = 0; i < n; ++i) { + xx[0] = x[i]; + xx[1] = y[i]; + xx[2] = z[i]; + // add the 3d-data coordinate, the predictor value (v[i]) and its errors + data.Add(xx, v[i], ev); + } + + TF3 * f3 = new TF3("f3","[0] * sin(x) + [1] * cos(y) + [2] * z",0,10,0,10,0,10); + f3->SetParameters(2,2,2); + ROOT::Fit::Fitter rfitter; + if (fitter.find("cmaes")!=std::string::npos) + rfitter.Config().SetMinimizer("cmaes","acmaes"); + // wrapped the TF1 in a IParamMultiFunction interface for teh Fitter class + ROOT::Math::WrappedMultiTF1 wf(*f3,3); + rfitter.SetFunction(wf); + TStopwatch timer; + timer.Start(); + bool ret = rfitter.Fit(data); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + const ROOT::Fit::FitResult & res = rfitter.Result(); + if (ret) { + // print result (should be around 1) + res.Print(std::cout); + // copy all fit result info (values, chi2, etc..) in TF3 + f3->SetFitResult(res); + // test fit p-value (chi2 probability) + double prob = res.Prob(); + if (prob < 1.E-2) + Error("exampleFit3D","Bad data fit - fit p-value is %f",prob); + else + std::cout << "Good fit : p-value = " << prob << std::endl; + + } + else Error("exampleFit3D","3D fit failed"); + + stats.add_exp(res.Status()==0,res.MinFcnValue(),res.Parameters(),cputime,res.NCalls()); + delete f3; + return stats; +}; + +/*- fit2 -*/ +class fit2_e : public experiment +{ +public: + fit2_e() + :experiment("fit2") + { + _h2 = new TH2F("h2","from f2",40,-10,10,40,-10,10); + f2 = new TF2("f2",fit2_e::fun22,-10,10,-10,10, _npar); + _ef = [this](const std::string &fitter) + { + expstats stats("fit2"); + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + + //Fit h2 with original function f2 + TStopwatch timer; + timer.Start(); + TFitResultPtr r = _h2->Fit("f2","S0"); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + return stats; + }; + } + + ~fit2_e() + { + delete _h2; + delete f2; + } + + virtual void Setup() + { + Double_t f2params[15] = + {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + f2->SetParameters(f2params); + _h2->FillRandom("f2",_nentries); + Float_t ratio = 4*_nentries/100000; + f2params[ 0] *= ratio; + f2params[ 5] *= ratio; + f2params[10] *= ratio; + f2->SetParameters(f2params); + } + + static Double_t g22(Double_t *x, Double_t *par) { + Double_t r1 = Double_t((x[0]-par[1])/par[2]); + Double_t r2 = Double_t((x[1]-par[3])/par[4]); + return par[0]*TMath::Exp(-0.5*(r1*r1+r2*r2)); + } + + static Double_t fun22(Double_t *x, Double_t *par) { + Double_t *p1 = &par[0]; + Double_t *p2 = &par[5]; + Double_t *p3 = &par[10]; + Double_t result = fit2_e::g22(x,p1) + fit2_e::g22(x,p2) + fit2_e::g22(x,p3); + return result; + } + + TH2F *_h2; + TF2 *f2; + Int_t _nentries = 100000; + Int_t _npar = 15; +}; +fit2_e gfit2; void run_experiments() { std::vector acmaes_stats; std::vector minuit2_stats; - std::map mexperiments; - mexperiments.insert(std::pair("gauss_fit",experiment_gauss_fit)); - mexperiments.insert(std::pair("lorentz_fit",experiment_lorentz_fit)); - mexperiments.insert(std::pair("gauss2D_fit",experiment_gauss2D_fit)); - mexperiments.insert(std::pair("fit2a",experiment_fit2a)); - mexperiments.insert(std::pair("fit2dhist",experiment_fit2dhist)); - std::map::iterator mit = mexperiments.begin(); + std::map mexperiments; + mexperiments.insert(std::pair(ggauss_fit._name,&ggauss_fit)); + mexperiments.insert(std::pair(glorentz_fit._name,&glorentz_fit)); + mexperiments.insert(std::pair(gfit2._name,&gfit2)); + std::map::iterator mit = mexperiments.begin(); while(mit!=mexperiments.end()) - { - acmaes_stats.push_back((*mit).second("acmaes")); - minuit2_stats.push_back((*mit).second("Minuit2")); - ++mit; - } - + { + //dynamic_cast(TVirtualFitter::GetFitter())->GetMinimizer()->Clear(); + (*mit).second->Setup(); + acmaes_stats.push_back((*mit).second->_ef("acmaes")); + minuit2_stats.push_back((*mit).second->_ef("Minuit2")); + (*mit).second->Cleanup(); + ++mit; + } + for (size_t i=0;i Date: Thu, 19 Jun 2014 12:51:45 +0200 Subject: [PATCH 38/98] added new functions to cmaes benchmark, in new format --- tutorials/fit/cmaesFullBench.C | 428 ++++++++++++++++++++------------- 1 file changed, 263 insertions(+), 165 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 27d6e6f7f7d26..f8a2e8369a26a 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -288,190 +288,285 @@ public: }; lorentz_fit_e glorentz_fit; -/*ExpFunc experiment_lorentz_fit = [](const std::string &fitter) +/*- gauss2D_fit -*/ +class gauss2D_fit_e : public experiment { - std::string ename = "lorentz_fit"; - expstats stats(ename); - int npass = 20; - gRandom = new TRandom3(); - TVirtualFitter::SetDefaultFitter(fitter.c_str()); - //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); - ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); - opts.SetIntValue("lambda",500); - - TF1 *fitFcn = new TF1("fitFcn",fitFunction,0,3,6); - fitFcn->SetNpx(200); - fitFcn->SetParameters(1,1,1,6,.03,1); - fitFcn->Update(); - std::string title = fitter + " fit bench"; - TH1 *histo = new TH1D(fitter.c_str(),title.c_str(),200,0,3); - for (Int_t pass=0;passSetParameters(1,1,1,6,.03,1); - for (Int_t i=0;i<5000;i++) { - histo->Fill(fitFcn->GetRandom()); - } - //histo->Print("all"); - timer.Start(); - TFitResultPtr r = histo->Fit(fitFcn,"QS0"); // from TH1.cxx: Q: quiet, 0: do not plot - timer.Stop(); - Double_t cputime = timer.CpuTime(); - stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); +public: + gauss2D_fit_e() + :experiment("gauss2D_fit") + { + _ef = [this](const std::string &fitter) + { + std::string ename = "gauss2D_fit"; + int npass = 0; + int n = 100000; + TStopwatch timer; + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + TF2 *fitFcn = new TF2("fitFcn",gauss2D_fit_e::fitFunction2,-10,10,-10,10,5); + fitFcn->SetParameters(100,0,0,2,7); + fitFcn->Update(); + timer.Start(); + TFitResultPtr r = _histo->Fit("fitFcn","S0"); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + printf("%s : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),timer.RealTime(),cputime); + delete fitFcn; + expstats stats(ename); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + std::cout << "gauss2D_fit stats: " << stats << std::endl; + return stats; + }; } - TStopwatch timer; - timer.Start(); - TFitResultPtr r = histo->Fit(fitFcn,"QS0"); // E: use Minos - timer.Stop(); - opts.SetIntValue("lambda",-1); - double cputime = timer.CpuTime(); - stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); - printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),npass,timer.RealTime(),cputime); - delete fitFcn; - delete histo; - std::cout << "lorentz_fit stats: " << stats << std::endl; - return stats; - };*/ -// Quadratic background function -Double_t gaus2D(Double_t *x, Double_t *par) { - double t1 = x[0] - par[1]; - double t2 = x[1] - par[2]; - return par[0]* exp( - 0.5 * ( t1*t1/( par[3]*par[3]) + t2*t2 /( par[4]*par[4] ) ) ) ; -} + ~gauss2D_fit_e() + { + if (_histo) + delete _histo; + } + + // Quadratic background function + static Double_t gaus2D(Double_t *x, Double_t *par) { + double t1 = x[0] - par[1]; + double t2 = x[1] - par[2]; + return par[0]* exp( - 0.5 * ( t1*t1/( par[3]*par[3]) + t2*t2 /( par[4]*par[4] ) ) ) ; + } -// Sum of background and peak function -Double_t fitFunction2(Double_t *x, Double_t *par) { - return gaus2D(x,par); -} + // Sum of background and peak function + static Double_t fitFunction2(Double_t *x, Double_t *par) { + return gaus2D(x,par); + } -void fillHisto(int n, - TH2D *histo) -{ - gRandom = new TRandom3(); - for (int i = 0; i < n; ++i) { - double x = gRandom->Gaus(2,3); - double y = gRandom->Gaus(-1,4); - histo->Fill(x,y,1.); + static void fillHisto(int n, + TH2D *histo) + { + gRandom = new TRandom3(); + for (int i = 0; i < n; ++i) { + double x = gRandom->Gaus(2,3); + double y = gRandom->Gaus(-1,4); + histo->Fill(x,y,1.); + } } -} -ExpFunc experiment_gauss2D_fit = [](const std::string &fitter) -{ - std::string ename = "gauss2D_fit"; - int npass = 0; - int n = 100000; - TStopwatch timer; - TVirtualFitter::SetDefaultFitter(fitter.c_str()); - TF2 *fitFcn = new TF2("fitFcn",fitFunction2,-10,10,-10,10,5); - fitFcn->SetParameters(100,0,0,2,7); - fitFcn->Update(); - TH2D *histo = new TH2D("h2","2D Gauss",100,-10,10,100,-10,10); - fillHisto(n,histo); - timer.Start(); - TFitResultPtr r = histo->Fit("fitFcn","S0"); - timer.Stop(); - Double_t cputime = timer.CpuTime(); - printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),npass,timer.RealTime(),cputime); - delete fitFcn; - delete histo; - expstats stats(ename); - stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); - std::cout << "gauss2D_fit stats: " << stats << std::endl; - return stats; -}; + virtual void Setup() + { + _histo = new TH2D("h2","2D Gauss",100,-10,10,100,-10,10); + fillHisto(_n,_histo); + } -Double_t g2(Double_t *x, Double_t *par) { - Double_t r1 = Double_t((x[0]-par[1])/par[2]); - Double_t r2 = Double_t((x[1]-par[3])/par[4]); - return par[0]*TMath::Exp(-0.5*(r1*r1+r2*r2)); -} -Double_t fun2(Double_t *x, Double_t *par) { - Double_t *p1 = &par[0]; - Double_t *p2 = &par[5]; - Double_t *p3 = &par[10]; - Double_t result = g2(x,p1) + g2(x,p2) + g2(x,p3); - return result; -} + virtual void Cleanup() + { + if (_histo) + delete _histo; + _histo = nullptr; + } -ExpFunc experiment_fit2a = [](const std::string &fitter) + int _n = 100000; + TH2D *_histo = nullptr; +}; +gauss2D_fit_e ggauss2D_fit; + +/*- fit2a -*/ +class fit2a_e : public experiment { - TVirtualFitter::SetDefaultFitter(fitter.c_str()); +public: + fit2a_e() + :experiment("fit2a") + { + _ef = [this](const std::string &fitter) + { + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + + //ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); + //ROOT::Math::IOptions *opts = ROOT::Math::MinimizerOptions::FindDefault(fitter); + //opts.SetIntValue("lambda",100); + //opts.SetNamedValue("fplot","fit2a.dat"); + + const Int_t npar = 15; + Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + TF2 *f2 = new TF2("f2",fun2,-10,10,-10,10, npar); + f2->SetParameters(f2params); + + //Fit h2 with original function f2 + Float_t ratio = 4*_nentries/100000; + f2params[ 0] *= ratio; + f2params[ 5] *= ratio; + f2params[10] *= ratio; + f2->SetParameters(f2params); + TStopwatch timer; + timer.Start(); + TFitResultPtr r = _h2->Fit("f2","SN0"); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + delete f2; + expstats stats("fit2a"); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + return stats; + }; + } - //ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); - //ROOT::Math::IOptions *opts = ROOT::Math::MinimizerOptions::FindDefault(fitter); - //opts.SetIntValue("lambda",100); - //opts.SetNamedValue("fplot","fit2a.dat"); + ~fit2a_e() + { + if (_h2) + delete _h2; + } - const Int_t npar = 15; - Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; - TF2 *f2 = new TF2("f2",fun2,-10,10,-10,10, npar); - f2->SetParameters(f2params); + static Double_t g2(Double_t *x, Double_t *par) { + Double_t r1 = Double_t((x[0]-par[1])/par[2]); + Double_t r2 = Double_t((x[1]-par[3])/par[4]); + return par[0]*TMath::Exp(-0.5*(r1*r1+r2*r2)); + } - //Create an histogram and fill it randomly with f2 - TH2F *h2 = new TH2F("h2","From f2",40,-10,10,40,-10,10); - Int_t nentries = 100000; - h2->FillRandom("f2",nentries); - //Fit h2 with original function f2 - Float_t ratio = 4*nentries/100000; - f2params[ 0] *= ratio; - f2params[ 5] *= ratio; - f2params[10] *= ratio; - f2->SetParameters(f2params); - TStopwatch timer; - timer.Start(); - TFitResultPtr r = h2->Fit("f2","SN0"); - timer.Stop(); - Double_t cputime = timer.CpuTime(); - delete f2; - delete h2; - expstats stats("fit2a"); - stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); - return stats; + static Double_t fun2(Double_t *x, Double_t *par) { + Double_t *p1 = &par[0]; + Double_t *p2 = &par[5]; + Double_t *p3 = &par[10]; + Double_t result = g2(x,p1) + g2(x,p2) + g2(x,p3); + return result; + } + + virtual void Setup() + { + _h2 = new TH2F("h2","From f2",40,-10,10,40,-10,10); + _h2->FillRandom("f2",_nentries); + } + + virtual void Cleanup() + { + if (_h2) + delete _h2; + _h2 = nullptr; + } + + int _nentries = 100000; + TH2F *_h2 = nullptr; }; +fit2a_e gfit2a; -double gauss2D(double *x, double *par) { - double z1 = double((x[0]-par[1])/par[2]); - double z2 = double((x[1]-par[3])/par[4]); - return par[0]*exp(-0.5*(z1*z1+z2*z2)); -} -double my2Dfunc(double *x, double *par) { - return gauss2D(x,&par[0]) + gauss2D(x,&par[5]); -} +/*- fit2dhist -*/ +class fit2dhist_e : public experiment +{ +public: + fit2dhist_e() + :experiment("fit2dhist") + { + _ef = [this](const std::string &fitter) + { + expstats stats("fit2dhist"); + TStopwatch timer; + timer.Start(); + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + TFitResultPtr r1 = _h1->Fit(_func,"S0"); + timer.Stop(); + Double_t cputime1 = timer.CpuTime(); + TStopwatch timer2; + timer2.Start(); + TFitResultPtr r2 = _h2->Fit(_func,"S0"); + timer2.Stop(); + Double_t cputime2 = timer2.CpuTime(); + + stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); + stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); + return stats; + }; + } + + ~fit2dhist_e() + { + Cleanup(); + } -void FillHisto2(TH2D * h, int n, double * p) -{ - const double mx1 = p[1]; - const double my1 = p[3]; - const double sx1 = p[2]; - const double sy1 = p[4]; - const double mx2 = p[6]; - const double my2 = p[8]; - const double sx2 = p[7]; - const double sy2 = p[9]; - //const double w1 = p[0]*sx1*sy1/(p[5]*sx2*sy2); - const double w1 = 0.5; - TRandom3 rndm; + static double gauss2D(double *x, double *par) { + double z1 = double((x[0]-par[1])/par[2]); + double z2 = double((x[1]-par[3])/par[4]); + return par[0]*exp(-0.5*(z1*z1+z2*z2)); + } - double x, y; - for (int i = 0; i < n; ++i) { - // generate randoms with larger gaussians - rndm.Rannor(x,y); - - double r = rndm.Rndm(1); - if (r < w1) { - x = x*sx1 + mx1; - y = y*sy1 + my1; + static double my2Dfunc(double *x, double *par) { + return gauss2D(x,&par[0]) + gauss2D(x,&par[5]); + } + + static void FillHisto2(TH2D * h, int n, double * p) + { + const double mx1 = p[1]; + const double my1 = p[3]; + const double sx1 = p[2]; + const double sy1 = p[4]; + const double mx2 = p[6]; + const double my2 = p[8]; + const double sx2 = p[7]; + const double sy2 = p[9]; + //const double w1 = p[0]*sx1*sy1/(p[5]*sx2*sy2); + const double w1 = 0.5; + TRandom3 rndm; + + double x, y; + for (int i = 0; i < n; ++i) { + // generate randoms with larger gaussians + rndm.Rannor(x,y); + + double r = rndm.Rndm(1); + if (r < w1) { + x = x*sx1 + mx1; + y = y*sy1 + my1; + } + else { + x = x*sx2 + mx2; + y = y*sy2 + my2; + } + h->Fill(x,y); } - else { - x = x*sx2 + mx2; - y = y*sy2 + my2; - } - h->Fill(x,y); } -} -ExpFunc experiment_fit2dhist_indep = [](const std::string &fitter) + void Setup() + { + int nbx1 = 50; + int nby1 = 50; + int nbx2 = 50; + int nby2 = 50; + double xlow1 = 0.; + double ylow1 = 0.; + double xup1 = 10.; + double yup1 = 10.; + double xlow2 = 5.; + double ylow2 = 5.; + double xup2 = 20.; + double yup2 = 20.; + _h1 = new TH2D("h1","core",nbx1,xlow1,xup1,nby1,ylow1,yup1); + _h2 = new TH2D("h2","tails",nbx2,xlow2,xup2,nby2,ylow2,yup2); + double iniParams[10] = { 100, 6., 2., 7., 3, 100, 12., 3., 11., 2. }; + _func = new TF2("func",fit2dhist_e::my2Dfunc,xlow2,xup2,ylow2,yup2, 10); + _func->SetParameters(iniParams); + int n1 = 1000000; + int n2 = 1000000; + FillHisto2(_h1,n1,iniParams); + FillHisto2(_h2,n2,iniParams); + // scale histograms to same heights (for fitting) + double dx1 = (xup1-xlow1)/double(nbx1); + double dy1 = (yup1-ylow1)/double(nby1); + double dx2 = (xup2-xlow2)/double(nbx2); + double dy2 = (yup2-ylow2)/double(nby2); + // scale histo 2 to scale of 1 + _h2->Sumw2(); + _h2->Scale( ( double(n1) * dx1 * dy1 ) / ( double(n2) * dx2 * dy2 ) ); + } + + void Cleanup() + { + if (_h1) + delete _h1; + if (_h2) + delete _h2; + if (_func) + delete _func; + } + + TH2D *_h1 = nullptr; + TH2D *_h2 = nullptr; + TF2 *_func = nullptr; +}; +fit2dhist_e gfit2dhist; + +/*ExpFunc experiment_fit2dhist_indep = [](const std::string &fitter) { expstats stats("fit2dhist"); int nbx1 = 50; @@ -527,7 +622,7 @@ ExpFunc experiment_fit2dhist_indep = [](const std::string &fitter) delete h1; delete h2; return stats; -}; + };*/ // definition of shared parameter // background function @@ -779,6 +874,9 @@ void run_experiments() mexperiments.insert(std::pair(ggauss_fit._name,&ggauss_fit)); mexperiments.insert(std::pair(glorentz_fit._name,&glorentz_fit)); mexperiments.insert(std::pair(gfit2._name,&gfit2)); + mexperiments.insert(std::pair(ggauss2D_fit._name,&ggauss2D_fit)); + mexperiments.insert(std::pair(gfit2a._name,&gfit2a)); + mexperiments.insert(std::pair(gfit2dhist._name,&gfit2dhist)); std::map::iterator mit = mexperiments.begin(); while(mit!=mexperiments.end()) { From 9e846530bf7e8df0dfc508082583edcb37c38fbf Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Thu, 19 Jun 2014 13:27:05 +0200 Subject: [PATCH 39/98] added combined fit cmaes benchmark to new format --- tutorials/fit/cmaesFullBench.C | 226 ++++++++++++++++++++------------- 1 file changed, 139 insertions(+), 87 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index f8a2e8369a26a..6e70c3619e973 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -566,100 +566,151 @@ public: }; fit2dhist_e gfit2dhist; -/*ExpFunc experiment_fit2dhist_indep = [](const std::string &fitter) +/*- combined_fit -*/ +class combined_fit_e : public experiment { - expstats stats("fit2dhist"); - int nbx1 = 50; - int nby1 = 50; - int nbx2 = 50; - int nby2 = 50; - double xlow1 = 0.; - double ylow1 = 0.; - double xup1 = 10.; - double yup1 = 10.; - double xlow2 = 5.; - double ylow2 = 5.; - double xup2 = 20.; - double yup2 = 20.; - - TH2D *h1 = new TH2D("h1","core",nbx1,xlow1,xup1,nby1,ylow1,yup1); - TH2D *h2 = new TH2D("h2","tails",nbx2,xlow2,xup2,nby2,ylow2,yup2); - - double iniParams[10] = { 100, 6., 2., 7., 3, 100, 12., 3., 11., 2. }; - // create fit function - TF2 * func = new TF2("func",my2Dfunc,xlow2,xup2,ylow2,yup2, 10); - func->SetParameters(iniParams); - - // fill Histos - int n1 = 1000000; - int n2 = 1000000; - FillHisto2(h1,n1,iniParams); - FillHisto2(h2,n2,iniParams); - - // scale histograms to same heights (for fitting) - double dx1 = (xup1-xlow1)/double(nbx1); - double dy1 = (yup1-ylow1)/double(nby1); - double dx2 = (xup2-xlow2)/double(nbx2); - double dy2 = (yup2-ylow2)/double(nby2); - // scale histo 2 to scale of 1 - h2->Sumw2(); - h2->Scale( ( double(n1) * dx1 * dy1 ) / ( double(n2) * dx2 * dy2 ) ); - - TStopwatch timer; - timer.Start(); - TVirtualFitter::SetDefaultFitter(fitter.c_str()); - TFitResultPtr r1 = h1->Fit(func,"S0"); - timer.Stop(); - Double_t cputime1 = timer.CpuTime(); - TStopwatch timer2; - timer2.Start(); - TFitResultPtr r2 = h2->Fit(func,"S0"); - timer2.Stop(); - Double_t cputime2 = timer2.CpuTime(); - - stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); - stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); - delete h1; - delete h2; - return stats; - };*/ - -// definition of shared parameter -// background function -int iparB[2] = { 0, // exp amplitude in B histo - 2 // exp common parameter -}; - -// signal + background function -int iparSB[5] = { 1, // exp amplitude in S+B histo - 2, // exp common parameter - 3, // gaussian amplitude - 4, // gaussian mean - 5 // gaussian sigma -}; - -struct GlobalChi2 { - GlobalChi2( ROOT::Math::IMultiGenFunction & f1, - ROOT::Math::IMultiGenFunction & f2) : +public: + struct GlobalChi2 { + GlobalChi2( ROOT::Math::IMultiGenFunction & f1, + ROOT::Math::IMultiGenFunction & f2) : fChi2_1(&f1), fChi2_2(&f2) {} + + // parameter vector is first background (in common 1 and 2) + // and then is signal (only in 2) + double operator() (const double *par) const { + int iparB[2] = {0,2}; + int iparSB[5] = {1,2,3,4,5}; + double p1[2]; + for (int i = 0; i < 2; ++i) p1[i] = par[iparB[i] ]; + + double p2[5]; + for (int i = 0; i < 5; ++i) p2[i] = par[iparSB[i] ]; + + return (*fChi2_1)(p1) + (*fChi2_2)(p2); + } + + const ROOT::Math::IMultiGenFunction * fChi2_1; + const ROOT::Math::IMultiGenFunction * fChi2_2; + }; + + combined_fit_e() + :experiment("combined_fit") + { + _ef = [this](const std::string &fitter) + { + expstats stats("combined"); - // parameter vector is first background (in common 1 and 2) - // and then is signal (only in 2) - double operator() (const double *par) const { - double p1[2]; - for (int i = 0; i < 2; ++i) p1[i] = par[iparB[i] ]; + // perform now global fit + TF1 * fSB = new TF1("fSB","expo + gaus(2)",0,100); + + ROOT::Math::WrappedMultiTF1 wfB(*_fB,1); + ROOT::Math::WrappedMultiTF1 wfSB(*fSB,1); + + ROOT::Fit::DataOptions opt; + ROOT::Fit::DataRange rangeB; + // set the data range + rangeB.SetRange(10,90); + ROOT::Fit::BinData dataB(opt,rangeB); + ROOT::Fit::FillData(dataB, _hB); + + ROOT::Fit::DataRange rangeSB; + rangeSB.SetRange(10,50); + ROOT::Fit::BinData dataSB(opt,rangeSB); + ROOT::Fit::FillData(dataSB, _hSB); + + ROOT::Fit::Chi2Function chi2_B(dataB, wfB); + ROOT::Fit::Chi2Function chi2_SB(dataSB, wfSB); + + GlobalChi2 globalChi2(chi2_B, chi2_SB); + + ROOT::Fit::Fitter rfitter; + + const int Npar = 6; + double par0[Npar] = { 5,5,-0.1,100, 30,10}; + + // create before the parameter settings in order to fix or set range on them + rfitter.Config().SetParamsSettings(6,par0); + // fix 5-th parameter + rfitter.Config().ParSettings(4).Fix(); + // set limits on the third and 4-th parameter + rfitter.Config().ParSettings(2).SetLimits(-10,-1.E-4); + rfitter.Config().ParSettings(3).SetLimits(0,10000); + rfitter.Config().ParSettings(3).SetStepSize(5); + + rfitter.Config().MinimizerOptions().SetPrintLevel(0); + if (fitter == "Minuit2") + rfitter.Config().SetMinimizer("Minuit2","Migrad"); + else if (fitter.find("cmaes")!=std::string::npos) + rfitter.Config().SetMinimizer("cmaes","acmaes"); + + // fit FCN function directly + // (specify optionally data size and flag to indicate that is a chi2 fit) + TStopwatch timer; + timer.Start(); + rfitter.FitFCN(6,globalChi2,0,dataB.Size()+dataSB.Size(),true); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + ROOT::Fit::FitResult r = rfitter.Result(); + //result.Print(std::cout); + + delete fSB; + + stats.add_exp(r.Status()==0,r.MinFcnValue(),r.Parameters(),cputime,r.NCalls()); + return stats; + }; + } - double p2[5]; - for (int i = 0; i < 5; ++i) p2[i] = par[iparSB[i] ]; + ~combined_fit_e() + { + Cleanup(); + } - return (*fChi2_1)(p1) + (*fChi2_2)(p2); - } + // definition of shared parameter + // background function + /*constexpr static int iparB[2] = { 0, // exp amplitude in B histo + 2 // exp common parameter + };*/ + + // signal + background function + /*constexpr static int iparSB[5] = { 1, // exp amplitude in S+B histo + 2, // exp common parameter + 3, // gaussian amplitude + 4, // gaussian mean + 5 // gaussian sigma + };*/ + virtual void Setup() + { + _hB = new TH1D("hB","histo B",100,0,100); + _hSB = new TH1D("hSB","histo S+B",100, 0,100); + _fB = new TF1("fB","expo",0,100); + _fB->SetParameters(1,-0.05); + _hB->FillRandom("fB"); + _fS = new TF1("fS","gaus",0,100); + _fS->SetParameters(1,30,5); + _hSB->FillRandom("fB",2000); + _hSB->FillRandom("fS",1000); + } - const ROOT::Math::IMultiGenFunction * fChi2_1; - const ROOT::Math::IMultiGenFunction * fChi2_2; + virtual void Cleanup() + { + if (_hB) + delete _hB; + if (_hSB) + delete _hSB; + if (_fB) + delete _fB; + if (_fS) + delete _fS; + } + + TH1D *_hB = nullptr; + TH1D *_hSB = nullptr; + TF1 *_fB = nullptr; + TF1 *_fS = nullptr; }; +combined_fit_e gcombined_fit; -ExpFunc experiment_combined = [](const std::string &fitter) +/*ExpFunc experiment_combined = [](const std::string &fitter) { expstats stats("combined"); @@ -738,7 +789,7 @@ ExpFunc experiment_combined = [](const std::string &fitter) stats.add_exp(r.Status()==0,r.MinFcnValue(),r.Parameters(),cputime,r.NCalls()); return stats; -}; + };*/ ExpFunc experiment_example3D = [](const std::string &fitter) { @@ -877,6 +928,7 @@ void run_experiments() mexperiments.insert(std::pair(ggauss2D_fit._name,&ggauss2D_fit)); mexperiments.insert(std::pair(gfit2a._name,&gfit2a)); mexperiments.insert(std::pair(gfit2dhist._name,&gfit2dhist)); + mexperiments.insert(std::pair(gcombined_fit._name,&gcombined_fit)); std::map::iterator mit = mexperiments.begin(); while(mit!=mexperiments.end()) { From 0d066886dcfc2b42bef2fb644b8e884e27eb932f Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Thu, 19 Jun 2014 15:40:34 +0200 Subject: [PATCH 40/98] completed migration of cmaes benchmarks --- tutorials/fit/cmaesFullBench.C | 218 +++++++++++++-------------------- 1 file changed, 83 insertions(+), 135 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 6e70c3619e973..848ab31300f71 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -710,148 +710,95 @@ public: }; combined_fit_e gcombined_fit; -/*ExpFunc experiment_combined = [](const std::string &fitter) +/*- ex3d -*/ +class ex3d_e : public experiment { - expstats stats("combined"); - - TH1D * hB = new TH1D("hB","histo B",100,0,100); - TH1D * hSB = new TH1D("hSB","histo S+B",100, 0,100); - - TF1 * fB = new TF1("fB","expo",0,100); - fB->SetParameters(1,-0.05); - hB->FillRandom("fB"); - - TF1 * fS = new TF1("fS","gaus",0,100); - fS->SetParameters(1,30,5); - - hSB->FillRandom("fB",2000); - hSB->FillRandom("fS",1000); +public: + ex3d_e() + :experiment("ex3d") + { + _ef = [this](const std::string &fitter) + { + expstats stats("example3D"); + double ev = 0.1; + + // create a 3d binned data structure + ROOT::Fit::BinData data(_n,3); + double xx[3]; + for(int i = 0; i < _n; ++i) { + xx[0] = _x[i]; + xx[1] = _y[i]; + xx[2] = _z[i]; + // add the 3d-data coordinate, the predictor value (v[i]) and its errors + data.Add(xx, _v[i], ev); + } + + TF3 * f3 = new TF3("f3","[0] * sin(x) + [1] * cos(y) + [2] * z",0,10,0,10,0,10); + f3->SetParameters(2,2,2); + ROOT::Fit::Fitter rfitter; + if (fitter.find("cmaes")!=std::string::npos) + rfitter.Config().SetMinimizer("cmaes","acmaes"); + // wrapped the TF1 in a IParamMultiFunction interface for the Fitter class + ROOT::Math::WrappedMultiTF1 wf(*f3,3); + rfitter.SetFunction(wf); + TStopwatch timer; + timer.Start(); + bool ret = rfitter.Fit(data); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + const ROOT::Fit::FitResult & res = rfitter.Result(); + if (ret) { + // print result (should be around 1) + res.Print(std::cout); + // copy all fit result info (values, chi2, etc..) in TF3 + f3->SetFitResult(res); + // test fit p-value (chi2 probability) + double prob = res.Prob(); + if (prob < 1.E-2) + Error("exampleFit3D","Bad data fit - fit p-value is %f",prob); + else + std::cout << "Good fit : p-value = " << prob << std::endl; + } + else Error("exampleFit3D","3D fit failed"); + + stats.add_exp(res.Status()==0,res.MinFcnValue(),res.Parameters(),cputime,res.NCalls()); + delete f3; + return stats; + }; + } - // perform now global fit - - TF1 * fSB = new TF1("fSB","expo + gaus(2)",0,100); - - ROOT::Math::WrappedMultiTF1 wfB(*fB,1); - ROOT::Math::WrappedMultiTF1 wfSB(*fSB,1); - - ROOT::Fit::DataOptions opt; - ROOT::Fit::DataRange rangeB; - // set the data range - rangeB.SetRange(10,90); - ROOT::Fit::BinData dataB(opt,rangeB); - ROOT::Fit::FillData(dataB, hB); - - ROOT::Fit::DataRange rangeSB; - rangeSB.SetRange(10,50); - ROOT::Fit::BinData dataSB(opt,rangeSB); - ROOT::Fit::FillData(dataSB, hSB); - - ROOT::Fit::Chi2Function chi2_B(dataB, wfB); - ROOT::Fit::Chi2Function chi2_SB(dataSB, wfSB); - - GlobalChi2 globalChi2(chi2_B, chi2_SB); - - ROOT::Fit::Fitter rfitter; - - const int Npar = 6; - double par0[Npar] = { 5,5,-0.1,100, 30,10}; - - // create before the parameter settings in order to fix or set range on them - rfitter.Config().SetParamsSettings(6,par0); - // fix 5-th parameter - rfitter.Config().ParSettings(4).Fix(); - // set limits on the third and 4-th parameter - rfitter.Config().ParSettings(2).SetLimits(-10,-1.E-4); - rfitter.Config().ParSettings(3).SetLimits(0,10000); - rfitter.Config().ParSettings(3).SetStepSize(5); - - rfitter.Config().MinimizerOptions().SetPrintLevel(0); - if (fitter == "Minuit2") - rfitter.Config().SetMinimizer("Minuit2","Migrad"); - else if (fitter.find("cmaes")!=std::string::npos) - rfitter.Config().SetMinimizer("cmaes","acmaes"); - - // fit FCN function directly - // (specify optionally data size and flag to indicate that is a chi2 fit) - TStopwatch timer; - timer.Start(); - rfitter.FitFCN(6,globalChi2,0,dataB.Size()+dataSB.Size(),true); - timer.Stop(); - Double_t cputime = timer.CpuTime(); - ROOT::Fit::FitResult r = rfitter.Result(); - //result.Print(std::cout); - - delete hB; - delete hSB; - delete fB; - delete fS; - delete fSB; - - stats.add_exp(r.Status()==0,r.MinFcnValue(),r.Parameters(),cputime,r.NCalls()); - return stats; - };*/ - -ExpFunc experiment_example3D = [](const std::string &fitter) -{ - expstats stats("example3D"); - const int n = 1000; - double x[n], y[n], z[n], v[n]; - double ev = 0.1; - - // generate the data - TRandom2 r; - for (int i = 0; i < n; ++i) { - x[i] = r.Uniform(0,10); - y[i] = r.Uniform(0,10); - z[i] = r.Uniform(0,10); - v[i] = sin(x[i] ) + cos(y[i]) + z[i] + r.Gaus(0,ev); + ~ex3d_e() + { } - - // create a 3d binned data structure - ROOT::Fit::BinData data(n,3); - double xx[3]; - for(int i = 0; i < n; ++i) { - xx[0] = x[i]; - xx[1] = y[i]; - xx[2] = z[i]; - // add the 3d-data coordinate, the predictor value (v[i]) and its errors - data.Add(xx, v[i], ev); + + virtual void Setup() + { + double ev = 0.1; + TRandom2 r; + for (int i = 0; i < _n; ++i) { + _x.push_back(r.Uniform(0,10)); + _y.push_back(r.Uniform(0,10)); + _z.push_back(r.Uniform(0,10)); + _v.push_back(sin(_x[i] ) + cos(_y[i]) + _z[i] + r.Gaus(0,ev)); + } } - - TF3 * f3 = new TF3("f3","[0] * sin(x) + [1] * cos(y) + [2] * z",0,10,0,10,0,10); - f3->SetParameters(2,2,2); - ROOT::Fit::Fitter rfitter; - if (fitter.find("cmaes")!=std::string::npos) - rfitter.Config().SetMinimizer("cmaes","acmaes"); - // wrapped the TF1 in a IParamMultiFunction interface for teh Fitter class - ROOT::Math::WrappedMultiTF1 wf(*f3,3); - rfitter.SetFunction(wf); - TStopwatch timer; - timer.Start(); - bool ret = rfitter.Fit(data); - timer.Stop(); - Double_t cputime = timer.CpuTime(); - const ROOT::Fit::FitResult & res = rfitter.Result(); - if (ret) { - // print result (should be around 1) - res.Print(std::cout); - // copy all fit result info (values, chi2, etc..) in TF3 - f3->SetFitResult(res); - // test fit p-value (chi2 probability) - double prob = res.Prob(); - if (prob < 1.E-2) - Error("exampleFit3D","Bad data fit - fit p-value is %f",prob); - else - std::cout << "Good fit : p-value = " << prob << std::endl; - + + virtual void Cleanup() + { + _x.clear(); + _y.clear(); + _z.clear(); + _v.clear(); } - else Error("exampleFit3D","3D fit failed"); - stats.add_exp(res.Status()==0,res.MinFcnValue(),res.Parameters(),cputime,res.NCalls()); - delete f3; - return stats; + int _n = 1000; + std::vector _x; + std::vector _y; + std::vector _z; + std::vector _v; }; - +ex3d_e gex3d; + /*- fit2 -*/ class fit2_e : public experiment { @@ -929,6 +876,7 @@ void run_experiments() mexperiments.insert(std::pair(gfit2a._name,&gfit2a)); mexperiments.insert(std::pair(gfit2dhist._name,&gfit2dhist)); mexperiments.insert(std::pair(gcombined_fit._name,&gcombined_fit)); + mexperiments.insert(std::pair(gex3d._name,&gex3d)); std::map::iterator mit = mexperiments.begin(); while(mit!=mexperiments.end()) { From a762f37a594d0875e6ab61ec04019b59bbb97f51 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Thu, 19 Jun 2014 16:30:21 +0200 Subject: [PATCH 41/98] added control of number of cmaes benchmark loops over functions --- tutorials/fit/cmaesFullBench.C | 43 ++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 848ab31300f71..95a3e7bdea785 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -63,7 +63,7 @@ public: else ++_ifails; _fdiff.push_back(fdiff); _cputime_diff.push_back(_cputime.at(i)-stats._cputime.at(i)); - _cputime_ratio.push_back(_cputime.at(i)/stats._cputime.at(i)); + _cputime_ratio.push_back((_cputime.at(i)+1)/(stats._cputime.at(i)+1)); _budget_diff.push_back(_budget.at(i)-stats._budget.at(i)); _budget_ratio.push_back(_budget.at(i)/stats._budget.at(i)); } @@ -381,23 +381,12 @@ public: //opts.SetIntValue("lambda",100); //opts.SetNamedValue("fplot","fit2a.dat"); - const Int_t npar = 15; - Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; - TF2 *f2 = new TF2("f2",fun2,-10,10,-10,10, npar); - f2->SetParameters(f2params); - //Fit h2 with original function f2 - Float_t ratio = 4*_nentries/100000; - f2params[ 0] *= ratio; - f2params[ 5] *= ratio; - f2params[10] *= ratio; - f2->SetParameters(f2params); TStopwatch timer; timer.Start(); TFitResultPtr r = _h2->Fit("f2","SN0"); timer.Stop(); Double_t cputime = timer.CpuTime(); - delete f2; expstats stats("fit2a"); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); return stats; @@ -406,8 +395,7 @@ public: ~fit2a_e() { - if (_h2) - delete _h2; + Cleanup(); } static Double_t g2(Double_t *x, Double_t *par) { @@ -426,8 +414,17 @@ public: virtual void Setup() { + const Int_t npar = 15; + Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + _f2 = new TF2("f2",fun2,-10,10,-10,10, npar); + _f2->SetParameters(f2params); _h2 = new TH2F("h2","From f2",40,-10,10,40,-10,10); _h2->FillRandom("f2",_nentries); + Float_t ratio = 4*_nentries/100000; + f2params[ 0] *= ratio; + f2params[ 5] *= ratio; + f2params[10] *= ratio; + _f2->SetParameters(f2params); } virtual void Cleanup() @@ -435,9 +432,13 @@ public: if (_h2) delete _h2; _h2 = nullptr; + if (_f2) + delete _f2; + _f2 = nullptr; } int _nentries = 100000; + TF2 *_f2 = nullptr; TH2F *_h2 = nullptr; }; fit2a_e gfit2a; @@ -864,7 +865,7 @@ public: }; fit2_e gfit2; -void run_experiments() +void run_experiments(const int &n=1) { std::vector acmaes_stats; std::vector minuit2_stats; @@ -880,11 +881,13 @@ void run_experiments() std::map::iterator mit = mexperiments.begin(); while(mit!=mexperiments.end()) { - //dynamic_cast(TVirtualFitter::GetFitter())->GetMinimizer()->Clear(); - (*mit).second->Setup(); - acmaes_stats.push_back((*mit).second->_ef("acmaes")); - minuit2_stats.push_back((*mit).second->_ef("Minuit2")); - (*mit).second->Cleanup(); + for (int i=0;iSetup(); + acmaes_stats.push_back((*mit).second->_ef("acmaes")); + minuit2_stats.push_back((*mit).second->_ef("Minuit2")); + (*mit).second->Cleanup(); + } ++mit; } From 862342d89ffc2ba84b84f6ebc5075569e5480dd0 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 20 Jun 2014 12:41:50 +0200 Subject: [PATCH 42/98] first release of the cmaes / minuit2 benchmark tool and visualization --- math/cmaes/test/cmaesFullBench.py | 81 ++++++++++++++++++++++++++++++ tutorials/fit/cmaesFullBench.C | 82 +++++++++++++++++++++++-------- 2 files changed, 142 insertions(+), 21 deletions(-) create mode 100644 math/cmaes/test/cmaesFullBench.py diff --git a/math/cmaes/test/cmaesFullBench.py b/math/cmaes/test/cmaesFullBench.py new file mode 100644 index 0000000000000..efe4b41ed1a39 --- /dev/null +++ b/math/cmaes/test/cmaesFullBench.py @@ -0,0 +1,81 @@ +import sys, csv +import numpy as np +import matplotlib.pyplot as plt +from numpy import * + +datfiles = ["combined.dat","example3D.dat","fit2a.dat","fit2.dat","fit2dhist.dat","gauss2D_fit.dat","gauss_fit.dat","lorentz_fit.dat"] + +#fig = plt.figure() +#ax = fig.add_subplot(211) +fig, axarr = plt.subplots(3,3) + +i = 0 +j = 0 +for f in datfiles: +# print i, j + + ## the data + dat = loadtxt(f,dtype=float,comments='#') +# print dat + + N = 4 +# print N + + cmaAvg = [dat[0,1],0.0,0.0,dat[0,7]]; + cmaStd = [0.0,0.0,0.0,0.0]; + minAvg = [dat[1,1],0.0,0.0,dat[1,1]+dat[1,2]-dat[0,7]]; + minStd = [0.0,0.0,0.0,0.0]; + + cmaAvg2 = [0.0,dat[0,3]*1000.0,dat[0,5],0.0]; + cmaStd2 = [0.0,dat[0,4]*1000.0,dat[0,6],0.0]; + minAvg2 = [0.0,dat[1,3]*1000.0,dat[1,5],0.0]; + minStd2 = [0.0,dat[1,4]*1000.0,dat[1,6],0.0]; + + ## necessary variables + #ind = np.arange(N) # the x locations for the groups + ind = array([2,1,0,3]) + width = 0.35 # the width of the bars + + ## the bars + ax2 = axarr[i,j].twinx() + rects1 = ax2.bar(ind, cmaAvg, width, + color='Teal', + yerr=cmaStd, + error_kw=dict(elinewidth=2,ecolor='red')) + + rects2 = ax2.bar(ind+width, minAvg, width, + color='LightGreen', + yerr=minStd, + error_kw=dict(elinewidth=2,ecolor='black')) + + rects12 = axarr[i,j].bar(ind, cmaAvg2, width, + color='Teal', + yerr=cmaStd2, + error_kw=dict(elinewidth=2,ecolor='red')) + + rects22 = axarr[i,j].bar(ind+width, minAvg2, width, + color='LightGreen', + yerr=minStd2, + error_kw=dict(elinewidth=2,ecolor='black')) + + # axes and labels + axarr[i,j].set_xlim(-width,len(ind)+width) + axarr[i,j].set_ylim(0) + ax2.set_xlim(-width,len(ind)+width) + ax2.set_ylim(0) + #axarr[i,j].set_ylabel('Scores') + axarr[i,j].set_title(f,fontsize=12) + xTickMarks = ["Found","CPU avg (ms)","Budget avg","best fmin"] + axarr[i,j].set_xticks(ind+width) + xtickNames = axarr[i,j].set_xticklabels(xTickMarks) + plt.setp(xtickNames, rotation=45, fontsize=10) + ## add a legend + if i == 0 and j == 0: + ax2.legend( (rects1[0], rects2[0]), ('aCMA-ES', 'Minuit2'), fontsize=10 ) + i = i + 1 + if i == 3: + i = 0 + j = j + 1 + +plt.tight_layout() +plt.show() diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 95a3e7bdea785..800e41e4204ab 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -23,8 +23,9 @@ class expstats { public: - expstats(const std::string &name): - _name(name) {} + expstats(const std::string &name, + const int &dim): + _name(name),_dim(dim) {} ~expstats() {} void add_exp(const bool &succ, @@ -36,12 +37,23 @@ public: if (succ) ++_succs; else ++_fails; + _vsuccs.push_back(succ); _fmin.push_back(fmin); _x.push_back(x); _cputime.push_back(cputime); _cpu_avg = std::accumulate(_cputime.begin(),_cputime.end(),0.0) / static_cast(_cputime.size()); + _cpu_std = stddev(_cputime,_cpu_avg); _budget.push_back(budget); _budget_avg = std::accumulate(_budget.begin(),_budget.end(),0.0) / static_cast(_budget.size()); + _budget_std = stddev(_budget,_budget_avg); + } + + void merge(const expstats &stats) + { + for (size_t i=0;i(_cputime_diff.size()); _cputime_ratio_avg = std::accumulate(_cputime_ratio.begin(),_cputime_ratio.end(),0.0) / static_cast(_cputime_ratio.size()); _budget_diff_avg = std::accumulate(_budget_diff.begin(),_budget_diff.end(),0.0) / static_cast(_budget_diff.size()); - _budget_ratio_avg = std::accumulate(_budget_ratio.begin(),_budget_ratio.end(),0.0) / static_cast(_budget_ratio.size()); + _budget_ratio_avg = std::accumulate(_budget_ratio.begin(),_budget_ratio.end(),0.0) / static_cast(_budget_ratio.size()); } + template double stddev(const std::vector &v, const double &avg) + { + double var = 0.0; + for (size_t i=0;i(v.size()); + return sqrt(var); + } + std::ostream& print(std::ostream &out) const { - out << _name << " / succs=" << _succs << " / fails=" << _fails << " / cpu_avg=" << _cpu_avg << " / budget_avg=" << _budget_avg << std::endl; + out << _name << " / dim=" << _dim << " / succs=" << _succs << " / fails=" << _fails << " / cpu_avg=" << _cpu_avg << " / budget_avg=" << _budget_avg << std::endl; return out; } std::ostream& print_diff(std::ostream &out) const { - out << _name << " / found=" << _found << "/" << _fdiff.size() << " / isuccs=" << _isuccs << " / ifails=" << _ifails << " / cpu_diff_avg=" << _cputime_diff_avg << " / cpu_ratio_avg=" << _cputime_ratio_avg << " / budget_diff_avg=" << _budget_diff_avg << " / budget_ratio_avg=" << _budget_ratio_avg << std::endl; + out << _name << " / dim=" << _dim << " / found=" << _found << "/" << _fdiff.size() << " / isuccs=" << _isuccs << " / ifails=" << _ifails << " / cpu_diff_avg=" << _cputime_diff_avg << " / cpu_ratio_avg=" << _cputime_ratio_avg << " / budget_diff_avg=" << _budget_diff_avg << " / budget_ratio_avg=" << _budget_ratio_avg << std::endl; for (size_t i=0;i<_fdiff.size();i++) { out << "#" << i << " - " << _name << ": " << "fdiff=" << _fdiff.at(i) << " / cputime_diff=" << _cputime_diff.at(i) << " / cputime_ratio=" << _cputime_ratio.at(i) << " / budget_diff=" << _budget_diff.at(i) << " / budget_ratio=" << _budget_ratio.at(i) << std::endl; @@ -89,15 +110,29 @@ public: return out; } + void print_avg_to_file() const + { + static std::string sep = "\t"; + static std::string ext = ".dat"; + std::ofstream fout(_name+ext,std::ofstream::out|std::ofstream::app); + fout << "#dim\tsuccs\tfails\tcpu_avg\tcpu_std\tbudget_avg\tbudget_std\tbest_fmin\n"; + fout << _dim << sep << _succs << sep << _fails << sep << _cpu_avg << sep << _cpu_std << sep << _budget_avg << sep << _budget_std << sep << _isuccs << std::endl; + fout.close(); + } + std::string _name; + int _dim = 0; int _fails = 0; int _succs = 0; + std::vector _vsuccs; std::vector _fmin; std::vector> _x; std::vector _cputime; double _cpu_avg = 0.0; + double _cpu_std = 0.0; std::vector _budget; double _budget_avg = 0.0; + double _budget_std = 0.0; // diff int _found = 0; @@ -172,7 +207,7 @@ public: delete h1; delete h1bis; - expstats stats(ename); + expstats stats(ename,r1->NTotalParameters()); stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); std::cout << "gaus_fit stats: " << stats << std::endl; @@ -207,7 +242,7 @@ public: _ef = [this](const std::string &fitter) { std::string ename = "lorentz_fit"; - expstats stats(ename); + expstats stats(ename,6); TVirtualFitter::SetDefaultFitter(fitter.c_str()); //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); @@ -311,7 +346,7 @@ public: Double_t cputime = timer.CpuTime(); printf("%s : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),timer.RealTime(),cputime); delete fitFcn; - expstats stats(ename); + expstats stats(ename,r->NTotalParameters()); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); std::cout << "gauss2D_fit stats: " << stats << std::endl; return stats; @@ -387,7 +422,7 @@ public: TFitResultPtr r = _h2->Fit("f2","SN0"); timer.Stop(); Double_t cputime = timer.CpuTime(); - expstats stats("fit2a"); + expstats stats("fit2a",r->NTotalParameters()); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); return stats; }; @@ -452,7 +487,6 @@ public: { _ef = [this](const std::string &fitter) { - expstats stats("fit2dhist"); TStopwatch timer; timer.Start(); TVirtualFitter::SetDefaultFitter(fitter.c_str()); @@ -464,7 +498,7 @@ public: TFitResultPtr r2 = _h2->Fit(_func,"S0"); timer2.Stop(); Double_t cputime2 = timer2.CpuTime(); - + expstats stats("fit2dhist",r1->NTotalParameters()); stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); return stats; @@ -599,8 +633,6 @@ public: { _ef = [this](const std::string &fitter) { - expstats stats("combined"); - // perform now global fit TF1 * fSB = new TF1("fSB","expo + gaus(2)",0,100); @@ -655,7 +687,7 @@ public: //result.Print(std::cout); delete fSB; - + expstats stats("combined",r.NTotalParameters()); stats.add_exp(r.Status()==0,r.MinFcnValue(),r.Parameters(),cputime,r.NCalls()); return stats; }; @@ -720,7 +752,6 @@ public: { _ef = [this](const std::string &fitter) { - expstats stats("example3D"); double ev = 0.1; // create a 3d binned data structure @@ -761,7 +792,7 @@ public: std::cout << "Good fit : p-value = " << prob << std::endl; } else Error("exampleFit3D","3D fit failed"); - + expstats stats("example3D",res.NTotalParameters()); stats.add_exp(res.Status()==0,res.MinFcnValue(),res.Parameters(),cputime,res.NCalls()); delete f3; return stats; @@ -811,15 +842,14 @@ public: f2 = new TF2("f2",fit2_e::fun22,-10,10,-10,10, _npar); _ef = [this](const std::string &fitter) { - expstats stats("fit2"); - TVirtualFitter::SetDefaultFitter(fitter.c_str()); - + TVirtualFitter::SetDefaultFitter(fitter.c_str()); //Fit h2 with original function f2 TStopwatch timer; timer.Start(); TFitResultPtr r = _h2->Fit("f2","S0"); timer.Stop(); Double_t cputime = timer.CpuTime(); + expstats stats("fit2",r->NTotalParameters()); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); return stats; }; @@ -884,8 +914,16 @@ void run_experiments(const int &n=1) for (int i=0;iSetup(); - acmaes_stats.push_back((*mit).second->_ef("acmaes")); - minuit2_stats.push_back((*mit).second->_ef("Minuit2")); + if (i == 0) + { + acmaes_stats.push_back((*mit).second->_ef("acmaes")); + minuit2_stats.push_back((*mit).second->_ef("Minuit2")); + } + else + { + acmaes_stats.back().merge((*mit).second->_ef("acmaes")); + minuit2_stats.back().merge((*mit).second->_ef("Minuit2")); + } (*mit).second->Cleanup(); } ++mit; @@ -895,5 +933,7 @@ void run_experiments(const int &n=1) { acmaes_stats.at(i).diff(minuit2_stats.at(i)); acmaes_stats.at(i).print_diff(std::cout); + acmaes_stats.at(i).print_avg_to_file(); + minuit2_stats.at(i).print_avg_to_file(); } } From d78d362dc99fe430ec06b800d8d5db7cbbda5c93 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 24 Jun 2014 10:56:52 +0200 Subject: [PATCH 43/98] added support for Edm to ROOT with CMA-ES, closes #6 --- math/cmaes/inc/CMAESMinimizer.h | 3 +-- math/cmaes/src/CMAESMinimizer.cxx | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index b5f37ed1aae37..4aba975d82aeb 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -134,8 +134,7 @@ namespace ROOT virtual double MinValue() const; /// return expected distance reached from the minimum - //TODO. - virtual double Edm() const { return -1.0;/*return fState.Edm();*/ } + virtual double Edm() const; /// return pointer to X values at the minimum virtual const double * X() const; diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index c458159de2090..bd6a2ebde7612 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -461,6 +461,14 @@ namespace ROOT return &fValues.front(); } + double TCMAESMinimizer::Edm() const + { + // XXX: cannot recompute it here as there's no access to the optimizer itself. + // instead this is returning the value computed at the end of last optimization call + // and stored within the solution object. + return fCMAsols._edm; + } + const double* TCMAESMinimizer::Errors() const { fErrors.clear(); From d716eaa38e02a45531f84e875614ff8376bd314a Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 24 Jun 2014 11:06:32 +0200 Subject: [PATCH 44/98] filled up missing functions in CMA-ES minimizer wrapper --- math/cmaes/inc/CMAESMinimizer.h | 4 ++-- math/cmaes/src/CMAESMinimizer.cxx | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 4aba975d82aeb..7e3cf2d4f1f24 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -94,7 +94,7 @@ namespace ROOT // set variable values virtual bool SetVariableValues(const double * val); /// set the step size of an already existing variable - //virtual bool SetVariableStepSize(unsigned int ivar, double step ); + virtual bool SetVariableStepSize(unsigned int ivar, double step ); /// set the lower-limit of an already existing variable virtual bool SetVariableLowerLimit(unsigned int ivar, double lower); /// set the upper-limit of an already existing variable @@ -107,7 +107,7 @@ namespace ROOT //virtual bool ReleaseVariable(unsigned int ivar); /// query if an existing variable is fixed (i.e. considered constant in the minimization) /// note that by default all variables are not fixed - //virtual bool IsFixedVariable(unsigned int ivar) const; + virtual bool IsFixedVariable(unsigned int ivar) const; /// get variable settings in a variable object (like ROOT::Fit::ParamsSettings) virtual bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings & varObj) const; /// get name of variables (override if minimizer support storing of variable names) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index bd6a2ebde7612..940ad612d9675 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -251,6 +251,14 @@ namespace ROOT return true; } + bool TCMAESMinimizer::SetVariableStepSize(unsigned int ivar, double step) + { + if (ivar > fInitialX.size()) + return false; + fInitialSigma[ivar] = step; + return true; + } + bool TCMAESMinimizer::SetVariableLowerLimit(unsigned int ivar, double lower) { if (ivar > fLBounds.size()) @@ -286,6 +294,14 @@ namespace ROOT { fFixedVariables.insert(std::pair(ivar,fInitialX.at(ivar))); // XXX: sets initial variable. } + + bool TCMAESMinimizer::IsFixedVariable(unsigned int ivar) const + { + std::map::const_iterator mit; + if ((mit=fFixedVariables.find(ivar))!=fFixedVariables.end()) + return true; + return false; + } bool TCMAESMinimizer::GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const { From 1609f4cdabc0ef7a192ef5d215e677a3acd687bd Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 24 Jun 2014 12:27:11 +0200 Subject: [PATCH 45/98] made CMA-ES minimizer's status compatible with those of Minuit2, closes #7 --- math/cmaes/inc/CMAESMinimizer.h | 4 ++-- math/cmaes/src/CMAESMinimizer.cxx | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 7e3cf2d4f1f24..09aa97b9b3720 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -122,8 +122,8 @@ namespace ROOT status code different than zero is set (retrieved by the derived method Minimizer::Status() )" - status = 1 : Covariance was made pos defined - status = 2 : Hesse is invalid + status = 1 : Covariance was made pos defined -> not yet implemented in libcmaes + status = 2 : Hesse is invalid => Not Applicable, kept for correspondence with Minuit2 status = 3 : Edm is above max status = 4 : Reached call limit status = 5 : Any other failure diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 940ad612d9675..624df0c6932ac 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -455,10 +455,14 @@ namespace ROOT fCMAparams = cmaparams; } Info("CMAESMinimizer","optimization status=%i",fCMAsols._run_status); - if (fCMAsols._run_status >= 0) - fStatus = 0; //TODO: convert so that to match that of Minuit2 ? + if (fCMAsols._edm > 10*fTol) // XXX: max edm seems to be left to each minimizer's internal implementation... + fStatus = 3; + else if (fCMAsols._run_status == 0 || fCMAsols._run_status == 1) + fStatus = 0; + else if (fCMAsols._run_status == 7 || fCMAsols._run_status == 9) + fStatus = 4; // reached budget limit. else fStatus = 5; - return fCMAsols._run_status >= 0; + return fCMAsols._run_status >= 0; // above 0 are partial successes at worst. } double TCMAESMinimizer::MinValue() const From 675ac58f5809a2a58670cb1073a8172c221efcc5 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 24 Jun 2014 12:33:17 +0200 Subject: [PATCH 46/98] clean up of CMA-ES minimizer header --- math/cmaes/inc/CMAESMinimizer.h | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 09aa97b9b3720..dd4feabebb529 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -256,7 +256,7 @@ namespace ROOT /// return reference to the objective function - ///virtual const ROOT::Math::IGenFunction & Function() const; + //virtual const ROOT::Math::IGenFunction & Function() const; /// print result of minimization virtual void PrintResults(); @@ -267,27 +267,8 @@ namespace ROOT /// set storage level = 1 : store all iteration states (default) /// = 0 : store only first and last state to save memory - void SetStorageLevel(int level); - - /// return the minimizer state (containing values, step size , etc..) - //const ROOT::Minuit2::MnUserParameterState & State() { return fState; } - - protected: - - // protected function for accessing the internal Minuit2 object. Needed for derived classes - - //virtual const ROOT::Minuit2::ModularFunctionMinimizer * GetMinimizer() const { return fMinimizer; } - //TODO. - //virtual void SetMinimizer( ROOT::Minuit2::ModularFunctionMinimizer * m) { fMinimizer = m; } - - //TODO. - //void SetMinimizerType( ROOT::Minuit2::EMinimizerType type); - - //virtual const ROOT::Minuit2::FCNBase * GetFCN() const { return fMinuitFCN; } - - /// examine the minimum result - //bool ExamineMinimum(const ROOT::Minuit2::FunctionMinimum & min); + void SetStorageLevel(int level); private: unsigned int fDim = 0; // dimension of the function to be minimized From 2a5bb1c1add4e40d18c31028dc95380197ffe39e Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 24 Jun 2014 14:17:40 +0200 Subject: [PATCH 47/98] logscale + fixes to benchmark suite for CMA-ES and plot --- math/cmaes/test/cmaesFullBench.py | 38 ++++++++++++++++++------------- tutorials/fit/cmaesFullBench.C | 15 +++++++----- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/math/cmaes/test/cmaesFullBench.py b/math/cmaes/test/cmaesFullBench.py index efe4b41ed1a39..c996fe8117518 100644 --- a/math/cmaes/test/cmaesFullBench.py +++ b/math/cmaes/test/cmaesFullBench.py @@ -11,26 +11,30 @@ i = 0 j = 0 +N = 4 +runs = -1 for f in datfiles: -# print i, j - - ## the data dat = loadtxt(f,dtype=float,comments='#') -# print dat - - N = 4 -# print N - - cmaAvg = [dat[0,1],0.0,0.0,dat[0,7]]; - cmaStd = [0.0,0.0,0.0,0.0]; - minAvg = [dat[1,1],0.0,0.0,dat[1,1]+dat[1,2]-dat[0,7]]; - minStd = [0.0,0.0,0.0,0.0]; - cmaAvg2 = [0.0,dat[0,3]*1000.0,dat[0,5],0.0]; - cmaStd2 = [0.0,dat[0,4]*1000.0,dat[0,6],0.0]; - minAvg2 = [0.0,dat[1,3]*1000.0,dat[1,5],0.0]; - minStd2 = [0.0,dat[1,4]*1000.0,dat[1,6],0.0]; + # best f-min + bestfmin1 = dat[0,7]+dat[0,8] + bestfmin2 = dat[0,8]+dat[0,9] + # successes and failures + cmaAvg = [dat[0,1],0.0,0.0,bestfmin1] + cmaStd = [0.0,0.0,0.0,0.0] + minAvg = [dat[1,1],0.0,0.0,bestfmin2] + minStd = [0.0,0.0,0.0,0.0] + + # budget and cpu averages + cmaAvg2 = [0.0,dat[0,3]*1000.0,dat[0,5],0.0] + cmaStd2 = [0.0,dat[0,4]*1000.0,dat[0,6],0.0] + minAvg2 = [0.0,dat[1,3]*1000.0,dat[1,5],0.0] + minStd2 = [0.0,dat[1,4]*1000.0,dat[1,6],0.0] + + if runs == -1: + runs = dat[0,1]+dat[0,2] # get the number of runs once. + ## necessary variables #ind = np.arange(N) # the x locations for the groups ind = array([2,1,0,3]) @@ -59,6 +63,7 @@ error_kw=dict(elinewidth=2,ecolor='black')) # axes and labels + axarr[i,j].set_yscale("log",nonposy='clip') axarr[i,j].set_xlim(-width,len(ind)+width) axarr[i,j].set_ylim(0) ax2.set_xlim(-width,len(ind)+width) @@ -78,4 +83,5 @@ j = j + 1 plt.tight_layout() +plt.suptitle('aCMA-ES / Minuit2 Benchmark Suite / ' + str(len(datfiles)) + ' experiments / ' + str(int(runs)) + ' runs on each') plt.show() diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 800e41e4204ab..4542e1b143934 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -68,10 +68,12 @@ public: double fdiff = _fmin.at(i)-stats._fmin.at(i); double ffdiff = fabs(fdiff); // should compare to tolerance but unable to access it. - if (ffdiff < 1e-2 || fdiff < 0.0) // ftol appears to default to 0.01 + if (ffdiff < 1e-2) // ftol appears to default to 0.01 ++_found; - if (fdiff <= 0.0) + if (ffdiff > 1e-2 && fdiff < 0.0) // ftol as 0.01 ++_isuccs; + else if (ffdiff < 1e-2) + ++_iequals; else ++_ifails; _fdiff.push_back(fdiff); _cputime_diff.push_back(_cputime.at(i)-stats._cputime.at(i)); @@ -115,8 +117,8 @@ public: static std::string sep = "\t"; static std::string ext = ".dat"; std::ofstream fout(_name+ext,std::ofstream::out|std::ofstream::app); - fout << "#dim\tsuccs\tfails\tcpu_avg\tcpu_std\tbudget_avg\tbudget_std\tbest_fmin\n"; - fout << _dim << sep << _succs << sep << _fails << sep << _cpu_avg << sep << _cpu_std << sep << _budget_avg << sep << _budget_std << sep << _isuccs << std::endl; + fout << "#dim\tsuccs\tfails\tcpu_avg\tcpu_std\tbudget_avg\tbudget_std\tbest_fmin\tequal_fmin\tfail_fmin\n"; + fout << _dim << sep << _succs << sep << _fails << sep << _cpu_avg << sep << _cpu_std << sep << _budget_avg << sep << _budget_std << sep << _isuccs << sep << _iequals << sep << _ifails << std::endl; fout.close(); } @@ -135,7 +137,7 @@ public: double _budget_std = 0.0; // diff - int _found = 0; + int _found = 0; /* number of times the correct minima was found. */ std::vector _fdiff; std::vector _cputime_diff; std::vector _cputime_ratio; @@ -145,8 +147,9 @@ public: double _cputime_ratio_avg = 1.0; double _budget_diff_avg = 0.0; double _budget_ratio_avg = 1.0; - int _isuccs = 0; + int _isuccs = 0; /* number of times the best f-min among the two algorithms, was found. */ int _ifails = 0; + int _iequals = 0; /* number of times the same fmin was found. */ }; std::ostream& operator<<(std::ostream &out, const expstats &stats) From d5ca1ae5da9c4bcf78d968e5743adf91750a9242 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 24 Jun 2014 15:08:31 +0200 Subject: [PATCH 48/98] improvements to CMA-ES benchmark suite --- math/cmaes/test/cmaesFullBench.py | 16 ++++++++-------- tutorials/fit/cmaesFullBench.C | 7 ++++--- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/math/cmaes/test/cmaesFullBench.py b/math/cmaes/test/cmaesFullBench.py index c996fe8117518..c6135d1e04fd3 100644 --- a/math/cmaes/test/cmaesFullBench.py +++ b/math/cmaes/test/cmaesFullBench.py @@ -17,8 +17,8 @@ dat = loadtxt(f,dtype=float,comments='#') # best f-min - bestfmin1 = dat[0,7]+dat[0,8] - bestfmin2 = dat[0,8]+dat[0,9] + bestfmin1 = dat[0,8] + bestfmin2 = dat[1,8] # successes and failures cmaAvg = [dat[0,1],0.0,0.0,bestfmin1] @@ -27,13 +27,13 @@ minStd = [0.0,0.0,0.0,0.0] # budget and cpu averages - cmaAvg2 = [0.0,dat[0,3]*1000.0,dat[0,5],0.0] - cmaStd2 = [0.0,dat[0,4]*1000.0,dat[0,6],0.0] - minAvg2 = [0.0,dat[1,3]*1000.0,dat[1,5],0.0] - minStd2 = [0.0,dat[1,4]*1000.0,dat[1,6],0.0] + cmaAvg2 = [0.0,dat[0,4]*1000.0,dat[0,6],0.0] + cmaStd2 = [0.0,dat[0,5]*1000.0,dat[0,7],0.0] + minAvg2 = [0.0,dat[1,4]*1000.0,dat[1,6],0.0] + minStd2 = [0.0,dat[1,5]*1000.0,dat[1,7],0.0] if runs == -1: - runs = dat[0,1]+dat[0,2] # get the number of runs once. + runs = dat[0,2]+dat[0,3] # get the number of runs once. ## necessary variables #ind = np.arange(N) # the x locations for the groups @@ -70,7 +70,7 @@ ax2.set_ylim(0) #axarr[i,j].set_ylabel('Scores') axarr[i,j].set_title(f,fontsize=12) - xTickMarks = ["Found","CPU avg (ms)","Budget avg","best fmin"] + xTickMarks = ["Found","CPU avg (ms)","Budget avg","wins"] axarr[i,j].set_xticks(ind+width) xtickNames = axarr[i,j].set_xticklabels(xTickMarks) plt.setp(xtickNames, rotation=45, fontsize=10) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 4542e1b143934..5234fa4fb23fe 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -68,7 +68,7 @@ public: double fdiff = _fmin.at(i)-stats._fmin.at(i); double ffdiff = fabs(fdiff); // should compare to tolerance but unable to access it. - if (ffdiff < 1e-2) // ftol appears to default to 0.01 + if (ffdiff < 1e-2 || fdiff < -1e-2) // ftol appears to default to 0.01 ++_found; if (ffdiff > 1e-2 && fdiff < 0.0) // ftol as 0.01 ++_isuccs; @@ -117,8 +117,8 @@ public: static std::string sep = "\t"; static std::string ext = ".dat"; std::ofstream fout(_name+ext,std::ofstream::out|std::ofstream::app); - fout << "#dim\tsuccs\tfails\tcpu_avg\tcpu_std\tbudget_avg\tbudget_std\tbest_fmin\tequal_fmin\tfail_fmin\n"; - fout << _dim << sep << _succs << sep << _fails << sep << _cpu_avg << sep << _cpu_std << sep << _budget_avg << sep << _budget_std << sep << _isuccs << sep << _iequals << sep << _ifails << std::endl; + fout << "#dim\tfound\tsuccs\tfails\tcpu_avg\tcpu_std\tbudget_avg\tbudget_std\tbest_fmin\tequal_fmin\tfail_fmin\n"; + fout << _dim << sep << _found << sep << _succs << sep << _fails << sep << _cpu_avg << sep << _cpu_std << sep << _budget_avg << sep << _budget_std << sep << _isuccs << sep << _iequals << sep << _ifails << std::endl; fout.close(); } @@ -935,6 +935,7 @@ void run_experiments(const int &n=1) for (size_t i=0;i Date: Wed, 25 Jun 2014 10:07:08 +0200 Subject: [PATCH 49/98] CMA-ES benchmark suite support for multiple lambda values --- tutorials/fit/cmaesFullBench.C | 96 ++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 5234fa4fb23fe..a2d88d8b71b90 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -24,8 +24,9 @@ class expstats { public: expstats(const std::string &name, - const int &dim): - _name(name),_dim(dim) {} + const int &dim, + const int &lambda=-1): + _name(name),_dim(dim),_lambda(lambda) {} ~expstats() {} void add_exp(const bool &succ, @@ -60,7 +61,7 @@ public: { if (_fmin.size() != stats._fmin.size()) { - std::cout << "Error: diff requires same size sets\n"; + std::cout << "Error: diff requires same size sets: lhs=" << _fmin.size() << " / rhs=" << stats._fmin.size() << std::endl; return; } for (size_t i=0;i<_fmin.size();i++) @@ -98,13 +99,13 @@ public: std::ostream& print(std::ostream &out) const { - out << _name << " / dim=" << _dim << " / succs=" << _succs << " / fails=" << _fails << " / cpu_avg=" << _cpu_avg << " / budget_avg=" << _budget_avg << std::endl; + out << _name << " / dim=" << _dim << " / lambda=" << _lambda << " / succs=" << _succs << " / fails=" << _fails << " / cpu_avg=" << _cpu_avg << " / budget_avg=" << _budget_avg << std::endl; return out; } std::ostream& print_diff(std::ostream &out) const { - out << _name << " / dim=" << _dim << " / found=" << _found << "/" << _fdiff.size() << " / isuccs=" << _isuccs << " / ifails=" << _ifails << " / cpu_diff_avg=" << _cputime_diff_avg << " / cpu_ratio_avg=" << _cputime_ratio_avg << " / budget_diff_avg=" << _budget_diff_avg << " / budget_ratio_avg=" << _budget_ratio_avg << std::endl; + out << _name << " / dim=" << _dim << " / lambda=" << _lambda << " / found=" << _found << "/" << _fdiff.size() << " / isuccs=" << _isuccs << " / ifails=" << _ifails << " / cpu_diff_avg=" << _cputime_diff_avg << " / cpu_ratio_avg=" << _cputime_ratio_avg << " / budget_diff_avg=" << _budget_diff_avg << " / budget_ratio_avg=" << _budget_ratio_avg << std::endl; for (size_t i=0;i<_fdiff.size();i++) { out << "#" << i << " - " << _name << ": " << "fdiff=" << _fdiff.at(i) << " / cputime_diff=" << _cputime_diff.at(i) << " / cputime_ratio=" << _cputime_ratio.at(i) << " / budget_diff=" << _budget_diff.at(i) << " / budget_ratio=" << _budget_ratio.at(i) << std::endl; @@ -117,8 +118,8 @@ public: static std::string sep = "\t"; static std::string ext = ".dat"; std::ofstream fout(_name+ext,std::ofstream::out|std::ofstream::app); - fout << "#dim\tfound\tsuccs\tfails\tcpu_avg\tcpu_std\tbudget_avg\tbudget_std\tbest_fmin\tequal_fmin\tfail_fmin\n"; - fout << _dim << sep << _found << sep << _succs << sep << _fails << sep << _cpu_avg << sep << _cpu_std << sep << _budget_avg << sep << _budget_std << sep << _isuccs << sep << _iequals << sep << _ifails << std::endl; + fout << "#dim\tlambda\tfound\tsuccs\tfails\tcpu_avg\tcpu_std\tbudget_avg\tbudget_std\tbest_fmin\tequal_fmin\tfail_fmin\n"; + fout << _dim << sep << _lambda << sep << _found << sep << _succs << sep << _fails << sep << _cpu_avg << sep << _cpu_std << sep << _budget_avg << sep << _budget_std << sep << _isuccs << sep << _iequals << sep << _ifails << std::endl; fout.close(); } @@ -136,6 +137,8 @@ public: double _budget_avg = 0.0; double _budget_std = 0.0; + int _lambda = -1; + // diff int _found = 0; /* number of times the correct minima was found. */ std::vector _fdiff; @@ -166,6 +169,13 @@ public: :_name(name) {} + void set_lambda(const int &lambda) + { + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetIntValue("lambda",lambda); + _lambda = lambda; + } + virtual ~experiment() {} virtual void Setup() {} @@ -174,6 +184,7 @@ public: ExpFunc _ef; std::string _name; + int _lambda = -1; }; /*- gauss_fit -*/ @@ -210,7 +221,7 @@ public: delete h1; delete h1bis; - expstats stats(ename,r1->NTotalParameters()); + expstats stats(ename,r1->NTotalParameters(),_lambda); stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); std::cout << "gaus_fit stats: " << stats << std::endl; @@ -297,8 +308,8 @@ public: virtual void Setup() { - ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); - opts.SetIntValue("lambda",500); + //ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + //opts.SetIntValue("lambda",500); _fitFcn->SetNpx(200); _fitFcn->SetParameters(1,1,1,6,.03,1); _fitFcn->Update(); @@ -313,8 +324,8 @@ public: virtual void Cleanup() { - ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); - opts.SetIntValue("lambda",-1); + //ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + //opts.SetIntValue("lambda",-1); for (int i=0;i<_npass;i++) delete _histos.at(i); _histos.clear(); @@ -900,44 +911,63 @@ fit2_e gfit2; void run_experiments(const int &n=1) { + std::vector lambdas = {-1, 5, 10, 20, 40, 80, 160, 320, 640, 1280}; std::vector acmaes_stats; std::vector minuit2_stats; std::map mexperiments; mexperiments.insert(std::pair(ggauss_fit._name,&ggauss_fit)); - mexperiments.insert(std::pair(glorentz_fit._name,&glorentz_fit)); + /*mexperiments.insert(std::pair(glorentz_fit._name,&glorentz_fit)); mexperiments.insert(std::pair(gfit2._name,&gfit2)); mexperiments.insert(std::pair(ggauss2D_fit._name,&ggauss2D_fit)); mexperiments.insert(std::pair(gfit2a._name,&gfit2a)); mexperiments.insert(std::pair(gfit2dhist._name,&gfit2dhist)); mexperiments.insert(std::pair(gcombined_fit._name,&gcombined_fit)); - mexperiments.insert(std::pair(gex3d._name,&gex3d)); + mexperiments.insert(std::pair(gex3d._name,&gex3d));*/ + int nexp = mexperiments.size(); + int cn = 0; std::map::iterator mit = mexperiments.begin(); while(mit!=mexperiments.end()) { for (int i=0;iSetup(); - if (i == 0) - { - acmaes_stats.push_back((*mit).second->_ef("acmaes")); + { + for (int j=0;j<(int)lambdas.size();j++) + { + (*mit).second->set_lambda(lambdas.at(j)); + (*mit).second->Setup(); + if (i == 0) + { + acmaes_stats.push_back((*mit).second->_ef("acmaes_l"+std::to_string(lambdas.at(j)))); + } + else + { + acmaes_stats.at(cn*(j+1)+j).merge((*mit).second->_ef("acmaes_l"+std::to_string(lambdas.at(j)))); + } + (*mit).second->Cleanup(); + } + (*mit).second->set_lambda(-1); // N/A to Minuit2 + (*mit).second->Setup(); + if (i == 0) minuit2_stats.push_back((*mit).second->_ef("Minuit2")); - } - else - { - acmaes_stats.back().merge((*mit).second->_ef("acmaes")); - minuit2_stats.back().merge((*mit).second->_ef("Minuit2")); - } - (*mit).second->Cleanup(); - } + else minuit2_stats.back().merge((*mit).second->_ef("Minuit2")); + (*mit).second->Cleanup(); + } + ++cn; ++mit; } - - for (size_t i=0;i fInitialX.size()) { - std::cout << "fDim=" << fDim << " / fInitialX size=" << fInitialX.size() << std::endl; + std::cout << "fDim=" << fDim << " / fInitialX size=" << fInitialX.size() << " / freeDim=" << fFreeDim << std::endl; MATH_ERROR_MSG("TCMAESMinimizer::Minimize","Dimension larger than initial X size's"); return false; } From 6a7ec922887cbbe62c1f062daa6c4d11af1a1f4e Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Wed, 25 Jun 2014 16:50:32 +0200 Subject: [PATCH 51/98] CMA-ES benchmark suite with multiple lambda values --- core/base/src/TPluginManager.cxx | 4 +- math/cmaes/test/cmaesFullBench.py | 139 +++++++++++++++++------------- tutorials/fit/cmaesFullBench.C | 33 +++---- 3 files changed, 98 insertions(+), 78 deletions(-) diff --git a/core/base/src/TPluginManager.cxx b/core/base/src/TPluginManager.cxx index c8b0f8cdd4a3c..9a3cd23ce7666 100644 --- a/core/base/src/TPluginManager.cxx +++ b/core/base/src/TPluginManager.cxx @@ -591,8 +591,8 @@ TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri) while ((h = (TPluginHandler*) next())) { if (h->CanHandle(base, uri)) { - if (gDebug > 0) - Info("FindHandler", "found plugin for %s", h->GetClass()); + /*if (gDebug > 0) + Info("FindHandler", "found plugin for %s", h->GetClass());*/ return h; } } diff --git a/math/cmaes/test/cmaesFullBench.py b/math/cmaes/test/cmaesFullBench.py index c6135d1e04fd3..6d7ae46ba1cbb 100644 --- a/math/cmaes/test/cmaesFullBench.py +++ b/math/cmaes/test/cmaesFullBench.py @@ -5,83 +5,100 @@ datfiles = ["combined.dat","example3D.dat","fit2a.dat","fit2.dat","fit2dhist.dat","gauss2D_fit.dat","gauss_fit.dat","lorentz_fit.dat"] -#fig = plt.figure() -#ax = fig.add_subplot(211) -fig, axarr = plt.subplots(3,3) +fig, axarr = plt.subplots(8,2) i = 0 j = 0 -N = 4 +N = 2 runs = -1 for f in datfiles: dat = loadtxt(f,dtype=float,comments='#') - - # best f-min - bestfmin1 = dat[0,8] - bestfmin2 = dat[1,8] - - # successes and failures - cmaAvg = [dat[0,1],0.0,0.0,bestfmin1] - cmaStd = [0.0,0.0,0.0,0.0] - minAvg = [dat[1,1],0.0,0.0,bestfmin2] - minStd = [0.0,0.0,0.0,0.0] - - # budget and cpu averages - cmaAvg2 = [0.0,dat[0,4]*1000.0,dat[0,6],0.0] - cmaStd2 = [0.0,dat[0,5]*1000.0,dat[0,7],0.0] - minAvg2 = [0.0,dat[1,4]*1000.0,dat[1,6],0.0] - minStd2 = [0.0,dat[1,5]*1000.0,dat[1,7],0.0] + nalgs = len(dat) if runs == -1: - runs = dat[0,2]+dat[0,3] # get the number of runs once. - - ## necessary variables - #ind = np.arange(N) # the x locations for the groups - ind = array([2,1,0,3]) - width = 0.35 # the width of the bars - - ## the bars - ax2 = axarr[i,j].twinx() - rects1 = ax2.bar(ind, cmaAvg, width, - color='Teal', - yerr=cmaStd, - error_kw=dict(elinewidth=2,ecolor='red')) + runs = dat[0,3]+dat[0,4] # get the number of runs once. + + hcolor = 'Teal' + aa = 0 + oldrec = None + for a in range(nalgs): + if a == nalgs-1: + hcolor = 'LightGreen' + + aavg1 = [dat[a,2],dat[a,9]] + aastd1 = [0.0,0.0] + aavg2 = [dat[a,5]*1000.0,dat[a,7]] + aastd2 = [dat[a,6]*1000.0,dat[a,8]] + + ## necessary variables + ind = np.arange(N) # the x locations for the groups + width = 0.05 # the width of the bars - rects2 = ax2.bar(ind+width, minAvg, width, - color='LightGreen', - yerr=minStd, - error_kw=dict(elinewidth=2,ecolor='black')) + ## the bars + rects1 = axarr[i,j+1].bar(ind+aa*width, aavg1, width, + color=hcolor, + yerr=aastd1, + error_kw=dict(elinewidth=2,ecolor='red')) + if a == 0: + oldrec = rects1 + + #rects2 = ax2.bar(ind+width, minAvg, width, + # color='LightGreen', + # yerr=minStd, + # error_kw=dict(elinewidth=2,ecolor='black')) - rects12 = axarr[i,j].bar(ind, cmaAvg2, width, - color='Teal', - yerr=cmaStd2, - error_kw=dict(elinewidth=2,ecolor='red')) + rects12 = axarr[i,j].bar(ind+aa*width, aavg2, width, + color=hcolor, + yerr=aastd2, + error_kw=dict(elinewidth=2,ecolor='red')) - rects22 = axarr[i,j].bar(ind+width, minAvg2, width, - color='LightGreen', - yerr=minStd2, - error_kw=dict(elinewidth=2,ecolor='black')) + #rects22 = axarr[i,j].bar(ind+width, minAvg2, width, + # color='LightGreen', + # yerr=minStd2, + # error_kw=dict(elinewidth=2,ecolor='black')) + + #add a legend + if i == 7: + axarr[7,1].legend((oldrec[0], rects12[0]), ('aCMA-ES', 'Minuit2'), fontsize=10 ) + aa = aa + 1 + + # axes and labels axarr[i,j].set_yscale("log",nonposy='clip') - axarr[i,j].set_xlim(-width,len(ind)+width) + #axarr[i,j].set_xlim(-width,len(ind)+width) axarr[i,j].set_ylim(0) - ax2.set_xlim(-width,len(ind)+width) - ax2.set_ylim(0) + #axarr[i,j+1].set_xlim(-width,len(ind)+width) + axarr[i,j+1].set_ylim(top=10) + if i == 4: + axarr[i,j+1].set_ylim(top=20) + if i == 7: + axarr[i,j+1].set_ylim(top=200) #axarr[i,j].set_ylabel('Scores') - axarr[i,j].set_title(f,fontsize=12) - xTickMarks = ["Found","CPU avg (ms)","Budget avg","wins"] - axarr[i,j].set_xticks(ind+width) - xtickNames = axarr[i,j].set_xticklabels(xTickMarks) - plt.setp(xtickNames, rotation=45, fontsize=10) - ## add a legend - if i == 0 and j == 0: - ax2.legend( (rects1[0], rects2[0]), ('aCMA-ES', 'Minuit2'), fontsize=10 ) + axarr[i,j].set_title(f + " / " + str(dat[0,0]) + "-D",fontsize=12) + #axarr[i,j].set_xticks(ind+width) + #axarr[i,j+1].set_xticks(ind+width) + plt.setp(axarr[i,j].get_xticklabels(),visible=False) + plt.setp(axarr[i,j+1].get_xticklabels(),visible=False) + if i == 7: + xTickMarks1 = ["CPU avg (ms)","","","","","Budget avg"] + xTickMarks2 = ["Found","","","","","wins"] + xtickNames = axarr[7,j].set_xticklabels(xTickMarks1) + plt.setp(xtickNames, rotation=45, fontsize=10) + xtickNames2 = axarr[7,j+1].set_xticklabels(xTickMarks2) + plt.setp(xtickNames2, rotation=45, fontsize=10) + plt.setp(axarr[i,j].get_xticklabels(),visible=True) + plt.setp(axarr[i,j+1].get_xticklabels(),visible=True) + + #add a legend +# if i == 6: +# axarr[7,1].legend()# (rects1[0], rects12[0]), ('aCMA-ES', 'Minuit2'), fontsize=10 ) i = i + 1 - if i == 3: - i = 0 - j = j + 1 + j = 0 +# if i == 2: +# i = 0 +# j = j + 1 -plt.tight_layout() -plt.suptitle('aCMA-ES / Minuit2 Benchmark Suite / ' + str(len(datfiles)) + ' experiments / ' + str(int(runs)) + ' runs on each') +#plt.tight_layout() +plt.suptitle('aCMA-ES / Minuit2 Benchmark Suite / ' + str(len(datfiles)) + ' experiments / ' + str(int(runs)) + ' runs on each\nlambda={auto, 5, 10, 20, 40, 80, 160, 320, 640, 1280}') plt.show() diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index a2d88d8b71b90..fa38c37e1694d 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -256,7 +256,7 @@ public: _ef = [this](const std::string &fitter) { std::string ename = "lorentz_fit"; - expstats stats(ename,6); + expstats stats(ename,6,_lambda); TVirtualFitter::SetDefaultFitter(fitter.c_str()); //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); @@ -360,7 +360,7 @@ public: Double_t cputime = timer.CpuTime(); printf("%s : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),timer.RealTime(),cputime); delete fitFcn; - expstats stats(ename,r->NTotalParameters()); + expstats stats(ename,r->NTotalParameters(),_lambda); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); std::cout << "gauss2D_fit stats: " << stats << std::endl; return stats; @@ -436,7 +436,7 @@ public: TFitResultPtr r = _h2->Fit("f2","SN0"); timer.Stop(); Double_t cputime = timer.CpuTime(); - expstats stats("fit2a",r->NTotalParameters()); + expstats stats("fit2a",r->NTotalParameters(),_lambda); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); return stats; }; @@ -512,7 +512,7 @@ public: TFitResultPtr r2 = _h2->Fit(_func,"S0"); timer2.Stop(); Double_t cputime2 = timer2.CpuTime(); - expstats stats("fit2dhist",r1->NTotalParameters()); + expstats stats("fit2dhist",r1->NTotalParameters(),_lambda); stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); return stats; @@ -678,7 +678,7 @@ public: // create before the parameter settings in order to fix or set range on them rfitter.Config().SetParamsSettings(6,par0); // fix 5-th parameter - rfitter.Config().ParSettings(4).Fix(); + //rfitter.Config().ParSettings(4).Fix(); // weird random crash, not yet understood: fitter tries to set variable 4 instead of 5, sometimes... // set limits on the third and 4-th parameter rfitter.Config().ParSettings(2).SetLimits(-10,-1.E-4); rfitter.Config().ParSettings(3).SetLimits(0,10000); @@ -694,6 +694,7 @@ public: // (specify optionally data size and flag to indicate that is a chi2 fit) TStopwatch timer; timer.Start(); + std::cout << "starting\n"; rfitter.FitFCN(6,globalChi2,0,dataB.Size()+dataSB.Size(),true); timer.Stop(); Double_t cputime = timer.CpuTime(); @@ -701,8 +702,10 @@ public: //result.Print(std::cout); delete fSB; - expstats stats("combined",r.NTotalParameters()); + expstats stats("combined",r.NTotalParameters(),_lambda); stats.add_exp(r.Status()==0,r.MinFcnValue(),r.Parameters(),cputime,r.NCalls()); + std::cout << "combined stats: " << stats << std::endl; + //std::cout << "fmin=" << r.MinFcnValue() << std::endl; return stats; }; } @@ -806,7 +809,7 @@ public: std::cout << "Good fit : p-value = " << prob << std::endl; } else Error("exampleFit3D","3D fit failed"); - expstats stats("example3D",res.NTotalParameters()); + expstats stats("example3D",res.NTotalParameters(),_lambda); stats.add_exp(res.Status()==0,res.MinFcnValue(),res.Parameters(),cputime,res.NCalls()); delete f3; return stats; @@ -863,7 +866,7 @@ public: TFitResultPtr r = _h2->Fit("f2","S0"); timer.Stop(); Double_t cputime = timer.CpuTime(); - expstats stats("fit2",r->NTotalParameters()); + expstats stats("fit2",r->NTotalParameters(),_lambda); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); return stats; }; @@ -915,12 +918,12 @@ void run_experiments(const int &n=1) std::vector acmaes_stats; std::vector minuit2_stats; std::map mexperiments; - mexperiments.insert(std::pair(ggauss_fit._name,&ggauss_fit)); - /*mexperiments.insert(std::pair(glorentz_fit._name,&glorentz_fit)); + /*mexperiments.insert(std::pair(ggauss_fit._name,&ggauss_fit)); + mexperiments.insert(std::pair(glorentz_fit._name,&glorentz_fit)); mexperiments.insert(std::pair(gfit2._name,&gfit2)); - mexperiments.insert(std::pair(ggauss2D_fit._name,&ggauss2D_fit)); + mexperiments.insert(std::pair(ggauss2D_fit._name,&ggauss2D_fit));*/ mexperiments.insert(std::pair(gfit2a._name,&gfit2a)); - mexperiments.insert(std::pair(gfit2dhist._name,&gfit2dhist)); + /*mexperiments.insert(std::pair(gfit2dhist._name,&gfit2dhist)); mexperiments.insert(std::pair(gcombined_fit._name,&gcombined_fit)); mexperiments.insert(std::pair(gex3d._name,&gex3d));*/ int nexp = mexperiments.size(); @@ -940,7 +943,7 @@ void run_experiments(const int &n=1) } else { - acmaes_stats.at(cn*(j+1)+j).merge((*mit).second->_ef("acmaes_l"+std::to_string(lambdas.at(j)))); + acmaes_stats.at(cn*(lambdas.size())+j).merge((*mit).second->_ef("acmaes_l"+std::to_string(lambdas.at(j)))); } (*mit).second->Cleanup(); } @@ -961,13 +964,13 @@ void run_experiments(const int &n=1) { for (size_t j=0;j + using namespace libcmaes; namespace ROOT @@ -91,8 +93,10 @@ namespace ROOT void TCMAESMinimizer::Clear() { + std::cout << "clearing up minimizer\n"; fCMAsols = CMASolutions(); - fCMAparams = CMAParameters<>(); + fCMAparams = CMAParameters>(); + fCMAparamsb = CMAParameters>(); fDim = 0; fFreeDim = 0; fLBounds.clear(); fUBounds.clear(); @@ -359,10 +363,10 @@ namespace ROOT if (cmaesOpt) cmaesOpt->Print(std::cout); - //TODO: phenotype / genotype. - FitFunc ffit = [this](const double *x, const int N) { + /*std::copy(x,x+N,std::ostream_iterator(std::cout," ")); + std::cout << std::endl;*/ return (*fObjFunc)(x); }; @@ -378,8 +382,24 @@ namespace ROOT return grad; }; } + + if (fWithBounds) + { + std::cout << "bounds:\n"; + std::copy(fLBounds.begin(),fLBounds.end(),std::ostream_iterator(std::cout," ")); + std::cout << std::endl; + std::copy(fUBounds.begin(),fUBounds.end(),std::ostream_iterator(std::cout," ")); + std::cout << std::endl; + } double sigma0 = *std::min_element(fInitialSigma.begin(),fInitialSigma.end()); + double sigma0scaled = 1e-1; + dVec vscaling = dVec::Constant(fDim,1.0); + for (size_t i=0;i,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; - GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); - CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0,lambda,0,gp); + //GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); + GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); cmaparams._algo = fMinimizer; if (gDebug > 0) cmaparams._quiet = false; @@ -428,13 +449,14 @@ namespace ROOT if (ftarget > 0.0) cmaparams.set_ftarget(ftarget); cmaparams._fplot = fplot; - fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparamsb = cmaparams; } else { //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; - CMAParameters<> cmaparams(fDim,&fInitialX.front(),sigma0,lambda); + GenoPheno gp(vscaling,vshift); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); cmaparams._algo = fMinimizer; if (gDebug > 0) cmaparams._quiet = false; @@ -451,7 +473,7 @@ namespace ROOT if (ftarget > 0.0) cmaparams.set_ftarget(ftarget); cmaparams._fplot = fplot; - fCMAsols = libcmaes::cmaes<>(ffit,cmaparams); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams = cmaparams; } Info("CMAESMinimizer","optimization status=%i",fCMAsols._run_status); @@ -472,12 +494,20 @@ namespace ROOT const double* TCMAESMinimizer::X() const { - //TODO: return pheno x when applicable (in solution object). - //std::cout << "X=" << fCMAsols.best_candidate()._x.transpose() << std::endl; fValues.clear(); Candidate bc = fCMAsols.best_candidate(); + + dVec x; + if (fWithBounds) + { + x = bc.get_x_pheno>(fCMAparamsb); + } + else + { + x = bc.get_x_pheno>(fCMAparams); + } for (int i=0;i::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize,fUp); + le = errstats>::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize,fUp); } else { fCMAparamsb.set_automaxiter(true); - le = errstats>::profile_likelihood(ffit,fCMAparamsb,fCMAsols,i,false,samplesize); + le = errstats>::profile_likelihood(ffit,fCMAparamsb,fCMAsols,i,false,samplesize); } errLow = le._errmin; errUp = le._errmax; return true; } - + bool TCMAESMinimizer::Scan(unsigned int i, unsigned int &nstep, double *x, double *y, double xmin, double xmax) { //TODO. From 4002d0c5df36106b85b950e4aa2d27a3eb3f796d Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 27 Jun 2014 12:42:45 +0200 Subject: [PATCH 54/98] added support for sigma as option to CMA-ES Minimizer --- math/cmaes/src/CMAESMinimizer.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index c82427920ba9e..13a8880a55eb9 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -393,7 +393,7 @@ namespace ROOT } double sigma0 = *std::min_element(fInitialSigma.begin(),fInitialSigma.end()); - double sigma0scaled = 1e-1; + double sigma0scaled = 1e-1; // default value. dVec vscaling = dVec::Constant(fDim,1.0); for (size_t i=0;iGetValue("sigma",sigma0scaled); cmaesOpt->GetValue("lambda",lambda); cmaesOpt->GetValue("noisy",noisy); cmaesOpt->GetValue("restarts",nrestarts); From 6af37c4897ba71154c9a0a205f4fa7994f0b0173 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 27 Jun 2014 13:15:31 +0200 Subject: [PATCH 55/98] added optional linear scaling to CMA-ES Minimizer, ref #5 --- math/cmaes/inc/CMAESMinimizer.h | 14 ++- math/cmaes/src/CMAESMinimizer.cxx | 156 +++++++++++++++++++----------- 2 files changed, 110 insertions(+), 60 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 6ae2f1726623e..06556e24e4bf8 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -115,6 +115,13 @@ namespace ROOT /// get index of variable given a variable given a name /// return -1 if variable is not found virtual int VariableIndex(const std::string & name) const; + + template + void SetMParameters(CMAParameters &cmaparams, + const int &maxiter, const int &maxfevals, + const int &noisy, const int &nrestarts, + const double &ftarget, + const std::string &fplot); /** method to perform the minimization. @@ -284,13 +291,16 @@ namespace ROOT std::vector fInitialSigma; // User-set Initial step-size for each variables. std::map fFixedVariables; // fixed variables and values. CMASolutions fCMAsols; - CMAParameters> fCMAparams; // params no bounds. - CMAParameters> fCMAparamsb; // params with bounds. + CMAParameters> fCMAparams; // params no bounds. + CMAParameters> fCMAparams_b; // params with bounds. + CMAParameters> fCMAparams_l; // params no bounds + linear scaling. + CMAParameters> fCMAparams_lb; // params with bounds + linear scaling. mutable std::vector fGlobalCC; // vector of global correlation coefficients. mutable std::vector fValues; // X values. mutable std::vector fErrors; // X errors. bool fWithBounds = false; // whether using box-type constraints as required by parameters. bool fWithGradient = false; // whether to use gradient information when available. + int fWithLinearScaling = 0; // wheter to use linear scaling of objective function parameters. */ }; } // end namespace cmaes diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 13a8880a55eb9..50c66d16acb72 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -95,8 +95,10 @@ namespace ROOT { std::cout << "clearing up minimizer\n"; fCMAsols = CMASolutions(); - fCMAparams = CMAParameters>(); - fCMAparamsb = CMAParameters>(); + fCMAparams = CMAParameters>(); + fCMAparams_b = CMAParameters>(); + fCMAparams_l = CMAParameters>(); + fCMAparams_lb = CMAParameters>(); fDim = 0; fFreeDim = 0; fLBounds.clear(); fUBounds.clear(); @@ -338,6 +340,31 @@ namespace ROOT return i; return -1; } + + template + void TCMAESMinimizer::SetMParameters(CMAParameters &cmaparams, + const int &maxiter, const int &maxfevals, + const int &noisy, const int &nrestarts, + const double &ftarget, + const std::string &fplot) + { + cmaparams._algo = fMinimizer; + if (gDebug > 0) + cmaparams._quiet = false; + else cmaparams._quiet = true; + for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) + cmaparams.set_fixed_p((*mit).first,(*mit).second); + cmaparams.set_ftolerance(fTol); + cmaparams.set_max_iter(maxiter); + cmaparams.set_max_fevals(maxfevals); + if (noisy > 0) + cmaparams.set_noisy(); + if (nrestarts > 0) + cmaparams.set_restarts(nrestarts); + if (ftarget > 0.0) + cmaparams.set_ftarget(ftarget); + cmaparams._fplot = fplot; + } bool TCMAESMinimizer::Minimize() { @@ -371,7 +398,7 @@ namespace ROOT }; // gradient function. - std::cout << "fWithGradient=" << fWithGradient << std::endl; + //std::cout << "fWithGradient=" << fWithGradient << std::endl; GradFunc gfit = nullptr; if (fWithGradient) { @@ -397,7 +424,7 @@ namespace ROOT dVec vscaling = dVec::Constant(fDim,1.0); for (size_t i=0;iGetValue("ftarget",ftarget); cmaesOpt->GetValue("fplot",fplot); + cmaesOpt->GetValue("lscaling",fWithLinearScaling); } if (gDebug > 0) { - std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0scaled << " / lambda=" << lambda << " / fTol=" << fTol << " / with_bounds=" << fWithBounds << " / maxiter=" << maxiter << " / maxfevals=" << maxfevals << std::endl; + std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0scaled << " / lambda=" << lambda << " / fTol=" << fTol << " / with_bounds=" << fWithBounds << " / with_gradient=" << fWithGradient << " / linear_scaling=" << fWithLinearScaling << " / maxiter=" << maxiter << " / maxfevals=" << maxfevals << std::endl; std::cout << "x0="; std::copy(fInitialX.begin(),fInitialX.end(),std::ostream_iterator(std::cout," ")); std::cout << std::endl; } - if (fWithBounds) + if (fWithLinearScaling) { - Info("CMAESMinimizer","Minimizing with bounds"); - //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; - //GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); - GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); - CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - cmaparams._algo = fMinimizer; - if (gDebug > 0) - cmaparams._quiet = false; - else cmaparams._quiet = true; - for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) - cmaparams.set_fixed_p((*mit).first,(*mit).second); - cmaparams.set_ftolerance(fTol); - cmaparams.set_max_iter(maxiter); - cmaparams.set_max_fevals(maxfevals); - if (noisy > 0) - cmaparams.set_noisy(); - if (nrestarts > 0) - cmaparams.set_restarts(nrestarts); - if (ftarget > 0.0) - cmaparams.set_ftarget(ftarget); - cmaparams._fplot = fplot; - fCMAsols = libcmaes::cmaes>(ffit,cmaparams); - fCMAparamsb = cmaparams; + if (fWithBounds) + { + Info("CMAESMinimizer","Minimizing with bounds"); + //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; + //GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); + GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + fCMAparams_lb = cmaparams; + } + else + { + //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; + GenoPheno gp(vscaling,vshift); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + fCMAparams_l = cmaparams; + } } else { - //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; - GenoPheno gp(vscaling,vshift); - CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - cmaparams._algo = fMinimizer; - if (gDebug > 0) - cmaparams._quiet = false; - else cmaparams._quiet = true; - for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) - cmaparams.set_fixed_p((*mit).first,(*mit).second); - cmaparams.set_ftolerance(fTol); - cmaparams.set_max_iter(maxiter); - cmaparams.set_max_fevals(maxfevals); - if (noisy > 0) - cmaparams.set_noisy(); - if (nrestarts > 0) - cmaparams.set_restarts(nrestarts); - if (ftarget > 0.0) - cmaparams.set_ftarget(ftarget); - cmaparams._fplot = fplot; - fCMAsols = libcmaes::cmaes>(ffit,cmaparams); - fCMAparams = cmaparams; + if (fWithBounds) + { + Info("CMAESMinimizer","Minimizing with bounds"); + GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + fCMAparams_b = cmaparams; + } + else + { + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + fCMAparams = cmaparams; + } } Info("CMAESMinimizer","optimization status=%i",fCMAsols._run_status); if (fCMAsols._edm > 10*fTol) // XXX: max edm seems to be left to each minimizer's internal implementation... @@ -499,13 +519,17 @@ namespace ROOT Candidate bc = fCMAsols.best_candidate(); dVec x; - if (fWithBounds) + if (fWithLinearScaling) { - x = bc.get_x_pheno>(fCMAparamsb); + if (fWithBounds) + x = bc.get_x_pheno>(fCMAparams_lb); + else x = bc.get_x_pheno>(fCMAparams_l); } else { - x = bc.get_x_pheno>(fCMAparams); + if (fWithBounds) + x = bc.get_x_pheno>(fCMAparams_b); + else x = bc.get_x_dvec(); } for (int i=0;i 0) std::cerr << "Computing 'Minos' confidence interval with profile likelihood on parameter " << i << " / samplesize=" << samplesize << " / with_bounds=" << fWithBounds << std::endl; pli le; - if (!fWithBounds) + if (fWithLinearScaling) { - fCMAparams.set_automaxiter(true); - le = errstats>::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize,fUp); + if (!fWithBounds) + { + fCMAparams_l.set_automaxiter(true); + le = errstats>::profile_likelihood(ffit,fCMAparams_l,fCMAsols,i,false,samplesize,fUp); + } + else + { + fCMAparams_lb.set_automaxiter(true); + le = errstats>::profile_likelihood(ffit,fCMAparams_lb,fCMAsols,i,false,samplesize); + } } else { - fCMAparamsb.set_automaxiter(true); - le = errstats>::profile_likelihood(ffit,fCMAparamsb,fCMAsols,i,false,samplesize); + if (!fWithBounds) + { + fCMAparams_l.set_automaxiter(true); + le = errstats>::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize,fUp); + } + else + { + fCMAparams_lb.set_automaxiter(true); + le = errstats>::profile_likelihood(ffit,fCMAparams_b,fCMAsols,i,false,samplesize); + } } errLow = le._errmin; errUp = le._errmax; From b02d5964154a8f55d70a03204b4fcff70ff18685 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 27 Jun 2014 13:22:06 +0200 Subject: [PATCH 56/98] added support for optional linear scaling to CMA-ES benchmark suite, ref #5 --- tutorials/fit/cmaesFullBench.C | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 7f20ed0d5916c..852942f30d434 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -175,6 +175,12 @@ public: opts.SetIntValue("lambda",lambda); _lambda = lambda; } + + void set_lscaling(const int &lscaling) + { + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetIntValue("lscaling",lscaling); + } virtual ~experiment() {} @@ -214,7 +220,7 @@ public: Double_t cputime1 = timer.CpuTime(); TStopwatch timer2; timer2.Start(); - TFitResultPtr r2 = h1bis->Fit("gaus","QLES0"); + TFitResultPtr r2 = h1bis->Fit("gaus","QLS0"); // E for Minos timer2.Stop(); Double_t cputime2 = timer2.CpuTime(); @@ -912,8 +918,12 @@ public: }; fit2_e gfit2; -void run_experiments(const int &n=1) +void run_experiments(const int &n=1, + const int &lscaling=0) { + std::cout << "Proceeding with " << n << " runs on every problems\n"; + if (lscaling > 0) + std::cout << "Linear scaling of parameters in ON\n"; std::vector lambdas = {-1, 5, 10, 20, 40, 80, 160, 320, 640, 1280}; std::vector acmaes_stats; std::vector minuit2_stats; @@ -936,6 +946,7 @@ void run_experiments(const int &n=1) for (int j=0;j<(int)lambdas.size();j++) { (*mit).second->set_lambda(lambdas.at(j)); + (*mit).second->set_lscaling(lscaling); (*mit).second->Setup(); if (i == 0) { From 56f92a8d1a56c9de38a6a23d2c3c41b044a6e6e0 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 27 Jun 2014 15:46:23 +0200 Subject: [PATCH 57/98] updated CMA-ES lorentz tutorial with control of sigma and lambda --- tutorials/fit/cmaesFitBench.C | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/tutorials/fit/cmaesFitBench.C b/tutorials/fit/cmaesFitBench.C index c7cfb12c192f0..3393b00bcc93d 100644 --- a/tutorials/fit/cmaesFitBench.C +++ b/tutorials/fit/cmaesFitBench.C @@ -47,7 +47,7 @@ Double_t fitFunction(Double_t *x, Double_t *par) { return background(x,par) + lorentzianPeak(x,&par[3]); } -void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { +void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass, Double_t sigma, Int_t lambda) { printf("\n*********************************************************************************\n"); printf("\t %s \n",fitter); printf("*********************************************************************************\n"); @@ -58,8 +58,10 @@ void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { TVirtualFitter::SetDefaultFitter(fitter); //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); - opts.SetIntValue("lambda",100); - + opts.SetIntValue("lambda",lambda); + opts.SetIntValue("lscaling",1); + opts.SetRealValue("sigma",sigma); + pad->SetGrid(); pad->SetLogy(); fitFcn->SetParameters(1,1,1,6,.03,1); @@ -75,7 +77,7 @@ void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { histo->Fill(fitFcn->GetRandom()); } //histo->Print("all"); - histo->Fit(fitFcn,"Q0"); // from TH1.cxx: Q: quiet, 0: do not plot + //histo->Fit(fitFcn,"Q0"); // from TH1.cxx: Q: quiet, 0: do not plot } histo->Fit(fitFcn,"V"); // E: use Minos, V: verbose. @@ -92,9 +94,13 @@ void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { p->SetTextColor(kRed+3); p->SetFillColor(kYellow-8); pad->Update(); + + //delete p; + //delete histo; + delete gRandom; } -void cmaesFitBench(Int_t npass=20) { +void cmaesFitBench(Int_t npass=20, Double_t sigma=0.1, Int_t lambda=-1) { if (!libloaded) { gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); @@ -113,19 +119,21 @@ void cmaesFitBench(Int_t npass=20) { //with Minuit2 c1->cd(1); - DoFit("Minuit2",gPad,npass); + DoFit("Minuit2",gPad,npass,sigma,lambda); //with Fumili c1->cd(2); - DoFit("Fumili",gPad,npass); + DoFit("Fumili",gPad,npass,sigma,lambda); //with cmaes c1->cd(3); - DoFit("cmaes",gPad,npass); + DoFit("cmaes",gPad,npass,sigma,lambda); //with acmaes c1->cd(4); - DoFit("acmaes",gPad,npass); + DoFit("acmaes",gPad,npass,sigma,lambda); //c1->SaveAs("FitBench.root"); + //delete c1; + delete fitFcn; } From 487b580813ca883b414671cb304a3e5b4a69d74b Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 1 Jul 2014 20:07:42 +0200 Subject: [PATCH 58/98] fixed sigma0 as conservative value when linear scaling is not activated and no sigma0 is specified for CMA-ES --- math/cmaes/src/CMAESMinimizer.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 50c66d16acb72..4eb1a6474917d 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -421,6 +421,8 @@ namespace ROOT double sigma0 = *std::min_element(fInitialSigma.begin(),fInitialSigma.end()); double sigma0scaled = 1e-1; // default value. + if (!fWithLinearScaling) + sigma0scaled = sigma0; dVec vscaling = dVec::Constant(fDim,1.0); for (size_t i=0;i Date: Wed, 2 Jul 2014 09:06:07 +0200 Subject: [PATCH 59/98] fixed configure so that libcmaes location is configurable from command line --- configure | 8 ++++++-- math/cmaes/test/Makefile | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/configure b/configure index cab77132e48d4..e4244a335f8bf 100755 --- a/configure +++ b/configure @@ -2163,6 +2163,8 @@ if test $# -gt 0 ; then --with-rfio-libdir=*) shiftlibdir=$optarg ; enable_rfio="yes" ;; --with-sqlite-incdir=*) sqliteincdir=$optarg ; enable_sqlite="yes" ;; --with-sqlite-libdir=*) sqlitelibdir=$optarg ; enable_sqlite="yes" ;; + --with-cmaes-incdir=*) cmaesincdir=$optarg ; enable_cmaes="yes" ;; + --with-cmaes-libdir=*) cmaeslibdir=$optarg ; enable_cmaes="yes" ;; --with-srp=*) srpdir=$optarg ; enable_srp="yes" ;; --with-srp-incdir=*) srpincdir=$optarg ; enable_srp="yes" ;; --with-srp-libdir=*) srplibdir=$optarg ; enable_srp="yes" ;; @@ -6591,10 +6593,12 @@ fi # ### echo %%% libcmaes support - Third party libraries # -check_header "cmaes.h" $HOME/include/libcmaes /usr/include/libcmaes +#check_header "cmaes.h" $HOME/include/libcmaes /usr/include/libcmaes +check_header "cmaes.h" "$cmaesincdir" /usr/include/libcmaes cmaesinc=$found_hdr cmaesincdir=$found_dir -check_library "libcmaes" "yes" $HOME/lib /usr/lib +check_library "libcmaes" "yes" "$cmaeslibdir" /usr/lib +# $HOME/lib /usr/lib cmaeslib=$found_lib cmaeslibdir=$found_dir diff --git a/math/cmaes/test/Makefile b/math/cmaes/test/Makefile index 077c535c41002..189834c4f7331 100644 --- a/math/cmaes/test/Makefile +++ b/math/cmaes/test/Makefile @@ -15,7 +15,6 @@ ifeq ($(PLATFORM),win32) EXTRALIBS = "$(ROOTSYS)/lib/libcmaesroot.lib" else EXTRALIBS = -lcmaesroot -lglog -lgflags -CXXFLAGS += -g -L/home/beniz/lib -L/usr/lib -L/usr/lib/x86_64-linux-gnu/ endif # for using with MPI From 473fccee2c99a40a2a5e8cde027f9c0cae3f2aed Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Wed, 2 Jul 2014 10:04:44 +0200 Subject: [PATCH 60/98] added computation of error bounds when geno/pheno tranform is active in CMA-ES + improved printing of results --- math/cmaes/src/CMAESMinimizer.cxx | 42 ++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 4eb1a6474917d..6186b45af0ede 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -410,14 +410,16 @@ namespace ROOT }; } - if (fWithBounds) + //debug + /*if (fWithBounds) { std::cout << "bounds:\n"; std::copy(fLBounds.begin(),fLBounds.end(),std::ostream_iterator(std::cout," ")); std::cout << std::endl; std::copy(fUBounds.begin(),fUBounds.end(),std::ostream_iterator(std::cout," ")); std::cout << std::endl; - } + }*/ + //debug double sigma0 = *std::min_element(fInitialSigma.begin(),fInitialSigma.end()); double sigma0scaled = 1e-1; // default value. @@ -437,7 +439,7 @@ namespace ROOT double ftarget = -1.0; std::string fplot; - //TODO: set hyper-parameters according to IOptions object. + // set hyper-parameters according to IOptions object. if (cmaesOpt) { cmaesOpt->GetValue("sigma",sigma0scaled); @@ -463,7 +465,6 @@ namespace ROOT { Info("CMAESMinimizer","Minimizing with bounds"); //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; - //GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot); @@ -549,10 +550,26 @@ namespace ROOT const double* TCMAESMinimizer::Errors() const { fErrors.clear(); - //std::cout << "diag=" << fCMAsols._cov.diagonal() << std::endl; - const double* diag = fCMAsols._cov.diagonal().data(); + //const double* diag = fCMAsols._cov.diagonal().data(); + dVec vgdiag; + if (fWithLinearScaling) + { + if (fWithBounds) + { + vgdiag = fCMAparams_lb._gp.pheno(dVec(fCMAsols._sigma*fCMAsols._cov.diagonal())); + } + else + { + vgdiag = fCMAparams_l._gp.pheno(dVec(fCMAsols._sigma*fCMAsols._cov.diagonal())); + } + } + else if (fWithBounds) + { + vgdiag = fCMAparams_b._gp.pheno(dVec(fCMAsols._sigma*fCMAsols._cov.diagonal())); + } + else vgdiag = fCMAsols._sigma*fCMAsols._cov.diagonal(); for (int i=0;i 1) + std::cout << "\t(limited)"; + std::cout << std::endl; } } From dd4dd96b980ca8e04861ac7f3a6adf11d34a09e8 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 7 Jul 2014 11:11:01 +0200 Subject: [PATCH 61/98] refactoring for new Minimizer getters for fTol, fUp and fMaxIter --- math/cmaes/src/CMAESMinimizer.cxx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 6186b45af0ede..3b8bc1afac5a7 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -354,7 +354,7 @@ namespace ROOT else cmaparams._quiet = true; for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) cmaparams.set_fixed_p((*mit).first,(*mit).second); - cmaparams.set_ftolerance(fTol); + cmaparams.set_ftolerance(Tolerance()); cmaparams.set_max_iter(maxiter); cmaparams.set_max_fevals(maxfevals); if (noisy > 0) @@ -432,8 +432,8 @@ namespace ROOT dVec vshift = dVec::Constant(fDim,0.0); int lambda = -1; - int maxiter = fMaxIter > 0 ? fMaxIter : -1; - int maxfevals = 100*fMaxCalls; // CMA-ES requires much more calls than Minuit. + int maxiter = MaxIterations() > 0 ? MaxIterations() : -1; + int maxfevals = 100*MaxFunctionCalls(); // CMA-ES requires much more calls than Minuit. //TODO: set into options... int noisy = 0; int nrestarts = -1; double ftarget = -1.0; @@ -453,7 +453,7 @@ namespace ROOT if (gDebug > 0) { - std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0scaled << " / lambda=" << lambda << " / fTol=" << fTol << " / with_bounds=" << fWithBounds << " / with_gradient=" << fWithGradient << " / linear_scaling=" << fWithLinearScaling << " / maxiter=" << maxiter << " / maxfevals=" << maxfevals << std::endl; + std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0scaled << " / lambda=" << lambda << " / fTol=" << Tolerance() << " / with_bounds=" << fWithBounds << " / with_gradient=" << fWithGradient << " / linear_scaling=" << fWithLinearScaling << " / maxiter=" << maxiter << " / maxfevals=" << maxfevals << std::endl; std::cout << "x0="; std::copy(fInitialX.begin(),fInitialX.end(),std::ostream_iterator(std::cout," ")); std::cout << std::endl; @@ -501,7 +501,7 @@ namespace ROOT } } Info("CMAESMinimizer","optimization status=%i",fCMAsols._run_status); - if (fCMAsols._edm > 10*fTol) // XXX: max edm seems to be left to each minimizer's internal implementation... + if (fCMAsols._edm > 10*Tolerance()) // XXX: max edm seems to be left to each minimizer's internal implementation... fStatus = 3; else if (fCMAsols._run_status == 0 || fCMAsols._run_status == 1) fStatus = 0; @@ -629,7 +629,7 @@ namespace ROOT if (!fWithBounds) { fCMAparams_l.set_automaxiter(true); - le = errstats>::profile_likelihood(ffit,fCMAparams_l,fCMAsols,i,false,samplesize,fUp); + le = errstats>::profile_likelihood(ffit,fCMAparams_l,fCMAsols,i,false,samplesize,ErrorDef()); } else { @@ -642,7 +642,7 @@ namespace ROOT if (!fWithBounds) { fCMAparams_l.set_automaxiter(true); - le = errstats>::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize,fUp); + le = errstats>::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize,ErrorDef()); } else { From 36cc741c7b0aabbe4f8290dad7ef33d560dc979f Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 11 Jul 2014 09:39:06 +0200 Subject: [PATCH 62/98] added support of numerical gradient injection to cma-es wrapper --- math/cmaes/inc/CMAESMinimizer.h | 4 +++- math/cmaes/src/CMAESMinimizer.cxx | 14 +++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 06556e24e4bf8..19a7dc3ef83b3 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -116,12 +116,14 @@ namespace ROOT /// return -1 if variable is not found virtual int VariableIndex(const std::string & name) const; + // sets libcmaes parameter object based on options. template void SetMParameters(CMAParameters &cmaparams, const int &maxiter, const int &maxfevals, const int &noisy, const int &nrestarts, const double &ftarget, - const std::string &fplot); + const std::string &fplot, + const bool &withnumgradient); /** method to perform the minimization. diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 3b8bc1afac5a7..4a7dd06577401 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -346,7 +346,8 @@ namespace ROOT const int &maxiter, const int &maxfevals, const int &noisy, const int &nrestarts, const double &ftarget, - const std::string &fplot) + const std::string &fplot, + const bool &withnumgradient) { cmaparams._algo = fMinimizer; if (gDebug > 0) @@ -364,6 +365,7 @@ namespace ROOT if (ftarget > 0.0) cmaparams.set_ftarget(ftarget); cmaparams._fplot = fplot; + cmaparams._with_gradient = withnumgradient; } bool TCMAESMinimizer::Minimize() @@ -438,6 +440,7 @@ namespace ROOT int nrestarts = -1; double ftarget = -1.0; std::string fplot; + int withnumgradient = 0; // whether to use numerical gradient injection. // set hyper-parameters according to IOptions object. if (cmaesOpt) @@ -449,6 +452,7 @@ namespace ROOT cmaesOpt->GetValue("ftarget",ftarget); cmaesOpt->GetValue("fplot",fplot); cmaesOpt->GetValue("lscaling",fWithLinearScaling); + cmaesOpt->GetValue("numgradient",withnumgradient); } if (gDebug > 0) @@ -467,7 +471,7 @@ namespace ROOT //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_lb = cmaparams; } @@ -476,7 +480,7 @@ namespace ROOT //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(vscaling,vshift); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_l = cmaparams; } @@ -488,14 +492,14 @@ namespace ROOT Info("CMAESMinimizer","Minimizing with bounds"); GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_b = cmaparams; } else { CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams = cmaparams; } From a1dc5204c4553696b8da5088e589465b509a4ccc Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 11 Jul 2014 09:56:41 +0200 Subject: [PATCH 63/98] change for setting edm with cma-es --- math/cmaes/src/CMAESMinimizer.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 4a7dd06577401..4163da89ac18d 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -355,6 +355,7 @@ namespace ROOT else cmaparams._quiet = true; for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) cmaparams.set_fixed_p((*mit).first,(*mit).second); + cmaparams.set_edm(true); // always activate EDM computation. cmaparams.set_ftolerance(Tolerance()); cmaparams.set_max_iter(maxiter); cmaparams.set_max_fevals(maxfevals); From e9406908ce4d364eddeb2352bdc0da08de6fcc5e Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 18 Aug 2014 14:54:47 +0200 Subject: [PATCH 64/98] update to the minuit/cmaes benchmark --- math/cmaes/test/cmaesFullBench.py | 6 +++--- tutorials/fit/cmaesFullBench.C | 36 ++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/math/cmaes/test/cmaesFullBench.py b/math/cmaes/test/cmaesFullBench.py index 6d7ae46ba1cbb..f94c50905d30b 100644 --- a/math/cmaes/test/cmaesFullBench.py +++ b/math/cmaes/test/cmaesFullBench.py @@ -58,8 +58,8 @@ # error_kw=dict(elinewidth=2,ecolor='black')) #add a legend - if i == 7: - axarr[7,1].legend((oldrec[0], rects12[0]), ('aCMA-ES', 'Minuit2'), fontsize=10 ) + if i == 6: + axarr[6,1].legend((oldrec[0], rects12[0]), ('aCMA-ES', 'Minuit2'), fontsize=10 ) aa = aa + 1 @@ -100,5 +100,5 @@ # j = j + 1 #plt.tight_layout() -plt.suptitle('aCMA-ES / Minuit2 Benchmark Suite / ' + str(len(datfiles)) + ' experiments / ' + str(int(runs)) + ' runs on each\nlambda={auto, 5, 10, 20, 40, 80, 160, 320, 640, 1280}') +plt.suptitle('aCMA-ES / Minuit2 Benchmark Suite / ' + str(len(datfiles)) + ' experiments / ' + str(int(runs)) + ' runs on each\nlambda={auto, 50, 200, auto-aipop-4-restarts}') #10, 20, 40, 80, 160, 320, 640, 1280}') plt.show() diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 852942f30d434..11977e4db8f93 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -181,6 +181,12 @@ public: ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); opts.SetIntValue("lscaling",lscaling); } + + void set_restarts(const int &nrestarts) + { + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetIntValue("restarts",nrestarts); + } virtual ~experiment() {} @@ -270,6 +276,9 @@ public: TStopwatch timer; //histos.at(i)->Print("all"); _fitFcn->SetParameters(1,1,1,6,.03,1); + for (Int_t i=0;i<5000;i++) { + _histos.at(pass)->Fill(_fitFcn->GetRandom()); + } timer.Start(); TFitResultPtr r = _histos.at(pass)->Fit(_fitFcn,"QS0"); // from TH1.cxx: Q: quiet, 0: do not plot timer.Stop(); @@ -693,8 +702,8 @@ public: rfitter.Config().MinimizerOptions().SetPrintLevel(0); if (fitter == "Minuit2") rfitter.Config().SetMinimizer("Minuit2","Migrad"); - else if (fitter.find("cmaes")!=std::string::npos) - rfitter.Config().SetMinimizer("cmaes","acmaes"); + else //if (fitter.find("cmaes")!=std::string::npos) + rfitter.Config().SetMinimizer("cmaes",fitter.c_str());//"acmaes"); // fit FCN function directly // (specify optionally data size and flag to indicate that is a chi2 fit) @@ -791,8 +800,10 @@ public: TF3 * f3 = new TF3("f3","[0] * sin(x) + [1] * cos(y) + [2] * z",0,10,0,10,0,10); f3->SetParameters(2,2,2); ROOT::Fit::Fitter rfitter; - if (fitter.find("cmaes")!=std::string::npos) - rfitter.Config().SetMinimizer("cmaes","acmaes"); + /*if (fitter.find("cmaes")!=std::string::npos) + rfitter.Config().SetMinimizer("cmaes","acmaes");*/ + if (fitter != "Minuit2") + rfitter.Config().SetMinimizer("cmaes",fitter.c_str()); // wrapped the TF1 in a IParamMultiFunction interface for the Fitter class ROOT::Math::WrappedMultiTF1 wf(*f3,3); rfitter.SetFunction(wf); @@ -924,7 +935,8 @@ void run_experiments(const int &n=1, std::cout << "Proceeding with " << n << " runs on every problems\n"; if (lscaling > 0) std::cout << "Linear scaling of parameters in ON\n"; - std::vector lambdas = {-1, 5, 10, 20, 40, 80, 160, 320, 640, 1280}; + //std::vector lambdas = {-1, 5, 10, 20, 40, 80, 160, 320, 640, 1280}; + std::vector lambdas = {-1, 50, 200, -2}; std::vector acmaes_stats; std::vector minuit2_stats; std::map mexperiments; @@ -945,16 +957,24 @@ void run_experiments(const int &n=1, { for (int j=0;j<(int)lambdas.size();j++) { - (*mit).second->set_lambda(lambdas.at(j)); + std::string fitter_name = "acmaes"; + if (lambdas.at(j) != -2) + (*mit).second->set_lambda(lambdas.at(j)); + else + { + (*mit).second->set_lambda(-1); + (*mit).second->set_restarts(4); + fitter_name = "aipop"; + } (*mit).second->set_lscaling(lscaling); (*mit).second->Setup(); if (i == 0) { - acmaes_stats.push_back((*mit).second->_ef("acmaes_l"+std::to_string(lambdas.at(j)))); + acmaes_stats.push_back((*mit).second->_ef(fitter_name));//_l"+std::to_string(lambdas.at(j)))); } else { - acmaes_stats.at(cn*(lambdas.size())+j).merge((*mit).second->_ef("acmaes_l"+std::to_string(lambdas.at(j)))); + acmaes_stats.at(cn*(lambdas.size())+j).merge((*mit).second->_ef(fitter_name));//_l"+std::to_string(lambdas.at(j)))); } (*mit).second->Cleanup(); } From da7bbd67674df926341e62ef2b32824c226fb0af Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Wed, 20 Aug 2014 18:06:24 +0200 Subject: [PATCH 65/98] major fix to CMA-ES / Minuit2 benchmark --- tutorials/fit/cmaesFullBench.C | 354 +++++++++++++++++---------------- 1 file changed, 188 insertions(+), 166 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 11977e4db8f93..a277e82222170 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -167,7 +167,10 @@ class experiment public: experiment(const std::string &name) :_name(name) - {} + { + /*ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetRealValue("sigma",0.1);*/ + } void set_lambda(const int &lambda) { @@ -211,22 +214,20 @@ public: std::string ename = "gauss_fit"; TVirtualFitter::SetDefaultFitter(fitter.c_str() ); - std::string name = "h1_" + fitter; - TH1D * h1 = new TH1D(name.c_str(),"Chi2 Fit",100, -5, 5. ); - name = "h1bis_" + fitter; - TH1D * h1bis = new TH1D(name.c_str(),"Likelihood Fit",100, -5, 5. ); + TH1D * h1 = new TH1D("h1f1","Chi2 Fit",100, -5, 5. ); + TH1D * h1bis = new TH1D("h1f2","Likelihood Fit",100, -5, 5. ); for (int i = 0; i < _n; ++i) { h1->Fill( _x.at(i) ); h1bis->Fill( _x.at(i) ); } TStopwatch timer; timer.Start(); - TFitResultPtr r1 = h1->Fit("gaus","QS0"); + TFitResultPtr r1 = h1->Fit("gaus","S0"); timer.Stop(); Double_t cputime1 = timer.CpuTime(); TStopwatch timer2; timer2.Start(); - TFitResultPtr r2 = h1bis->Fit("gaus","QLS0"); // E for Minos + TFitResultPtr r2 = h1bis->Fit("gaus","LS0"); timer2.Stop(); Double_t cputime2 = timer2.CpuTime(); @@ -237,7 +238,7 @@ public: stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); std::cout << "gaus_fit stats: " << stats << std::endl; - + std::cout << "fmin1=" << r1->MinFcnValue() << std::endl;//" / fmin2=" << r2->MinFcnValue() << std::endl; return stats; }; } @@ -264,45 +265,52 @@ public: lorentz_fit_e() :experiment("lorentz_fit") { - _fitFcn = new TF1("fitFcn",lorentz_fit_e::fitFunction,0,3,6); _ef = [this](const std::string &fitter) { + std::string title = "fit bench"; std::string ename = "lorentz_fit"; expstats stats(ename,6,_lambda); TVirtualFitter::SetDefaultFitter(fitter.c_str()); - //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); + TH1D *mhisto =new TH1D("fit",title.c_str(),200,0,3); for (Int_t pass=0;pass<_npass;pass++) { TStopwatch timer; - //histos.at(i)->Print("all"); - _fitFcn->SetParameters(1,1,1,6,.03,1); - for (Int_t i=0;i<5000;i++) { - _histos.at(pass)->Fill(_fitFcn->GetRandom()); - } + TF1 *fitFcn = new TF1("fitFcn",lorentz_fit_e::fitFunction,0,3,6); + fitFcn->SetParameters(1,1,1,6,.03,1); + TH1D *histo = new TH1D("fit2",title.c_str(),200,0,3); + //histo->Print("all"); + for (Int_t j=0;j<5000;j++) + { + histo->Fill(_xs.at(pass).at(j)); + mhisto->Fill(_xs.at(pass).at(j)); + } timer.Start(); - TFitResultPtr r = _histos.at(pass)->Fit(_fitFcn,"QS0"); // from TH1.cxx: Q: quiet, 0: do not plot + TFitResultPtr r = histo->Fit(fitFcn,"QS0"); // from TH1.cxx: Q: quiet, 0: do not plot timer.Stop(); Double_t cputime = timer.CpuTime(); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + delete histo; + delete fitFcn; } TStopwatch timer; timer.Start(); - TFitResultPtr r = _histos.back()->Fit(_fitFcn,"QS0"); // E: use Minos + TF1 *fitFcn = new TF1("fitFcn",lorentz_fit_e::fitFunction,0,3,6); + fitFcn->SetParameters(1,1,1,6,.03,1); + TFitResultPtr r = mhisto->Fit(fitFcn,"QS0"); timer.Stop(); double cputime = timer.CpuTime(); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),_npass,timer.RealTime(),cputime); - std::cout << "lorentz_fit stats: " << stats << std::endl; + //std::cout << "lorentz_fit stats: " << stats << std::endl; + delete mhisto; + delete fitFcn; return stats; }; } virtual ~lorentz_fit_e() { - delete _fitFcn; - for (int i=0;i<_npass;i++) - delete _histos.at(i); - _histos.clear(); + _xs.clear(); } // Quadratic background function @@ -323,32 +331,29 @@ public: virtual void Setup() { - //ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); - //opts.SetIntValue("lambda",500); - _fitFcn->SetNpx(200); - _fitFcn->SetParameters(1,1,1,6,.03,1); - _fitFcn->Update(); - std::string title = "fit bench"; - TH1D *histo = new TH1D("fit",title.c_str(),200,0,3); + TF1 *fitFcn = new TF1("fitFcn",lorentz_fit_e::fitFunction,0,3,6); + fitFcn->SetNpx(200); + fitFcn->SetParameters(1,1,1,6,.03,1); + fitFcn->Update(); + std::vector x; for (int i=0;i<_npass;i++) { - histo->Fill(_fitFcn->GetRandom()); - _histos.push_back(new TH1D(*histo)); + for (Int_t j=0;j<5000;j++) { + x.push_back(fitFcn->GetRandom()); + } + _xs.push_back(x); } + delete fitFcn; } virtual void Cleanup() { - //ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); - //opts.SetIntValue("lambda",-1); - for (int i=0;i<_npass;i++) - delete _histos.at(i); - _histos.clear(); + _xs.clear(); } int _npass = 20; - TF1 *_fitFcn; - std::vector _histos; + //TF1 *_fitFcn; + std::vector > _xs; }; lorentz_fit_e glorentz_fit; @@ -428,7 +433,7 @@ public: TH2D *_histo = nullptr; }; gauss2D_fit_e ggauss2D_fit; - + /*- fit2a -*/ class fit2a_e : public experiment { @@ -438,21 +443,30 @@ public: { _ef = [this](const std::string &fitter) { + const Int_t npar = 15; TVirtualFitter::SetDefaultFitter(fitter.c_str()); - - //ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); - //ROOT::Math::IOptions *opts = ROOT::Math::MinimizerOptions::FindDefault(fitter); - //opts.SetIntValue("lambda",100); - //opts.SetNamedValue("fplot","fit2a.dat"); + TF2 *f2 = new TF2("f2",fun2,-10,10,-10,10, npar); + TH2F *h2 = new TH2F("h2","From f2",40,-10,10,40,-10,10); + for (int i=0;i<_nentries;i++) + h2->Fill(_x.at(i),_y.at(i)); + + Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + Float_t ratio = 4*_nentries/100000; + f2params[ 0] *= ratio; + f2params[ 5] *= ratio; + f2params[10] *= ratio; + f2->SetParameters(f2params); //Fit h2 with original function f2 TStopwatch timer; timer.Start(); - TFitResultPtr r = _h2->Fit("f2","SN0"); + TFitResultPtr r = h2->Fit("f2","SN0"); timer.Stop(); Double_t cputime = timer.CpuTime(); expstats stats("fit2a",r->NTotalParameters(),_lambda); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + delete h2; + delete f2; return stats; }; } @@ -480,30 +494,21 @@ public: { const Int_t npar = 15; Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; - _f2 = new TF2("f2",fun2,-10,10,-10,10, npar); - _f2->SetParameters(f2params); - _h2 = new TH2F("h2","From f2",40,-10,10,40,-10,10); - _h2->FillRandom("f2",_nentries); - Float_t ratio = 4*_nentries/100000; - f2params[ 0] *= ratio; - f2params[ 5] *= ratio; - f2params[10] *= ratio; - _f2->SetParameters(f2params); + TF2 *f2 = new TF2("f2",fun2,-10,10,-10,10, npar); + f2->SetParameters(f2params); + _x = std::vector(_nentries); + _y = std::vector(_nentries); + for (int i=0;i<_nentries;i++) + f2->GetRandom2(_x.at(i),_y.at(i)); + delete f2; } virtual void Cleanup() { - if (_h2) - delete _h2; - _h2 = nullptr; - if (_f2) - delete _f2; - _f2 = nullptr; } int _nentries = 100000; - TF2 *_f2 = nullptr; - TH2F *_h2 = nullptr; + std::vector _x,_y; }; fit2a_e gfit2a; @@ -516,20 +521,62 @@ public: { _ef = [this](const std::string &fitter) { + int nbx1 = 50; + int nby1 = 50; + int nbx2 = 50; + int nby2 = 50; + double xlow1 = 0.; + double ylow1 = 0.; + double xup1 = 10.; + double yup1 = 10.; + double xlow2 = 5.; + double ylow2 = 5.; + double xup2 = 20.; + double yup2 = 20.; + TH2D *h1 = new TH2D("h1","core",nbx1,xlow1,xup1,nby1,ylow1,yup1); + TH2D *h2 = new TH2D("h2","tails",nbx2,xlow2,xup2,nby2,ylow2,yup2); + double iniParams[10] = { 100, 6., 2., 7., 3, 100, 12., 3., 11., 2. }; + TF2 *func1 = new TF2("func",fit2dhist_e::my2Dfunc,xlow2,xup2,ylow2,yup2, 10); + func1->SetParameters(iniParams); + TF2 *func2 = new TF2("func",fit2dhist_e::my2Dfunc,xlow2,xup2,ylow2,yup2, 10); + func2->SetParameters(iniParams); + + // fill up histograms. + int n1 = 1000000; + int n2 = 1000000; + for (int i=0;iFill(_xr1.at(i),_yr1.at(i)); + h2->Fill(_xr2.at(i),_yr2.at(i)); // since n1 == n2. + } + + // scale histograms to same heights (for fitting) + double dx1 = (xup1-xlow1)/double(nbx1); + double dy1 = (yup1-ylow1)/double(nby1); + double dx2 = (xup2-xlow2)/double(nbx2); + double dy2 = (yup2-ylow2)/double(nby2); + // scale histo 2 to scale of 1 + h2->Sumw2(); + h2->Scale( ( double(n1) * dx1 * dy1 ) / ( double(n2) * dx2 * dy2 ) ); + TStopwatch timer; timer.Start(); TVirtualFitter::SetDefaultFitter(fitter.c_str()); - TFitResultPtr r1 = _h1->Fit(_func,"S0"); + TFitResultPtr r1 = h1->Fit(func1,"S0"); timer.Stop(); Double_t cputime1 = timer.CpuTime(); TStopwatch timer2; timer2.Start(); - TFitResultPtr r2 = _h2->Fit(_func,"S0"); + TFitResultPtr r2 = h2->Fit(func2,"S0"); timer2.Stop(); Double_t cputime2 = timer2.CpuTime(); expstats stats("fit2dhist",r1->NTotalParameters(),_lambda); stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); + delete h1; + delete h2; + delete func1; + delete func2; return stats; }; } @@ -549,7 +596,7 @@ public: return gauss2D(x,&par[0]) + gauss2D(x,&par[5]); } - static void FillHisto2(TH2D * h, int n, double * p) + static void FillHisto2(std::vector &xr, std::vector &yr, int n, double * p) { const double mx1 = p[1]; const double my1 = p[3]; @@ -561,14 +608,13 @@ public: const double sy2 = p[9]; //const double w1 = p[0]*sx1*sy1/(p[5]*sx2*sy2); const double w1 = 0.5; - TRandom3 rndm; double x, y; for (int i = 0; i < n; ++i) { // generate randoms with larger gaussians - rndm.Rannor(x,y); + fit2dhist_e::_rndm.Rannor(x,y); - double r = rndm.Rndm(1); + double r = fit2dhist_e::_rndm.Rndm(1); if (r < w1) { x = x*sx1 + mx1; y = y*sy1 + my1; @@ -576,17 +622,14 @@ public: else { x = x*sx2 + mx2; y = y*sy2 + my2; - } - h->Fill(x,y); + } + xr.push_back(x); + yr.push_back(y); } } void Setup() { - int nbx1 = 50; - int nby1 = 50; - int nbx2 = 50; - int nby2 = 50; double xlow1 = 0.; double ylow1 = 0.; double xup1 = 10.; @@ -595,39 +638,21 @@ public: double ylow2 = 5.; double xup2 = 20.; double yup2 = 20.; - _h1 = new TH2D("h1","core",nbx1,xlow1,xup1,nby1,ylow1,yup1); - _h2 = new TH2D("h2","tails",nbx2,xlow2,xup2,nby2,ylow2,yup2); double iniParams[10] = { 100, 6., 2., 7., 3, 100, 12., 3., 11., 2. }; - _func = new TF2("func",fit2dhist_e::my2Dfunc,xlow2,xup2,ylow2,yup2, 10); - _func->SetParameters(iniParams); int n1 = 1000000; - int n2 = 1000000; - FillHisto2(_h1,n1,iniParams); - FillHisto2(_h2,n2,iniParams); - // scale histograms to same heights (for fitting) - double dx1 = (xup1-xlow1)/double(nbx1); - double dy1 = (yup1-ylow1)/double(nby1); - double dx2 = (xup2-xlow2)/double(nbx2); - double dy2 = (yup2-ylow2)/double(nby2); - // scale histo 2 to scale of 1 - _h2->Sumw2(); - _h2->Scale( ( double(n1) * dx1 * dy1 ) / ( double(n2) * dx2 * dy2 ) ); + int n2 = 1000000; + FillHisto2(_xr1,_yr1,n1,iniParams); + FillHisto2(_xr2,_yr2,n2,iniParams); } void Cleanup() { - if (_h1) - delete _h1; - if (_h2) - delete _h2; - if (_func) - delete _func; } - TH2D *_h1 = nullptr; - TH2D *_h2 = nullptr; - TF2 *_func = nullptr; + static TRandom3 _rndm; + std::vector _xr1,_yr1,_xr2,_yr2; }; +TRandom3 fit2dhist_e::_rndm = TRandom3(); fit2dhist_e gfit2dhist; /*- combined_fit -*/ @@ -702,8 +727,7 @@ public: rfitter.Config().MinimizerOptions().SetPrintLevel(0); if (fitter == "Minuit2") rfitter.Config().SetMinimizer("Minuit2","Migrad"); - else //if (fitter.find("cmaes")!=std::string::npos) - rfitter.Config().SetMinimizer("cmaes",fitter.c_str());//"acmaes"); + else rfitter.Config().SetMinimizer("cmaes",fitter.c_str()); // fit FCN function directly // (specify optionally data size and flag to indicate that is a chi2 fit) @@ -720,7 +744,7 @@ public: expstats stats("combined",r.NTotalParameters(),_lambda); stats.add_exp(r.Status()==0,r.MinFcnValue(),r.Parameters(),cputime,r.NCalls()); std::cout << "combined stats: " << stats << std::endl; - //std::cout << "fmin=" << r.MinFcnValue() << std::endl; + std::cout << "fmin=" << r.MinFcnValue() << std::endl; return stats; }; } @@ -730,19 +754,6 @@ public: Cleanup(); } - // definition of shared parameter - // background function - /*constexpr static int iparB[2] = { 0, // exp amplitude in B histo - 2 // exp common parameter - };*/ - - // signal + background function - /*constexpr static int iparSB[5] = { 1, // exp amplitude in S+B histo - 2, // exp common parameter - 3, // gaussian amplitude - 4, // gaussian mean - 5 // gaussian sigma - };*/ virtual void Setup() { _hB = new TH1D("hB","histo B",100,0,100); @@ -872,40 +883,52 @@ public: fit2_e() :experiment("fit2") { - _h2 = new TH2F("h2","from f2",40,-10,10,40,-10,10); - f2 = new TF2("f2",fit2_e::fun22,-10,10,-10,10, _npar); _ef = [this](const std::string &fitter) - { + { TVirtualFitter::SetDefaultFitter(fitter.c_str()); + TF2 *f2 = new TF2("f2",fit2_e::fun22,-10,10,-10,10, _npar); + + Double_t f2params[15] = + {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + Float_t ratio = 4*_nentries/100000; + f2params[ 0] *= ratio; + f2params[ 5] *= ratio; + f2params[10] *= ratio; + f2->SetParameters(f2params); + + TH2F *h2 = new TH2F("h2","from f2",40,-10,10,40,-10,10); + for (int i=0;i<_nentries;i++) + h2->Fill(_x.at(i),_y.at(i)); + //Fit h2 with original function f2 TStopwatch timer; timer.Start(); - TFitResultPtr r = _h2->Fit("f2","S0"); + TFitResultPtr r = h2->Fit("f2","S0"); timer.Stop(); Double_t cputime = timer.CpuTime(); expstats stats("fit2",r->NTotalParameters(),_lambda); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + delete h2; + delete f2; return stats; }; } ~fit2_e() { - delete _h2; - delete f2; } virtual void Setup() { + TF2 *f2 = new TF2("f2",fit2_e::fun22,-10,10,-10,10, _npar); Double_t f2params[15] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; f2->SetParameters(f2params); - _h2->FillRandom("f2",_nentries); - Float_t ratio = 4*_nentries/100000; - f2params[ 0] *= ratio; - f2params[ 5] *= ratio; - f2params[10] *= ratio; - f2->SetParameters(f2params); + _x = std::vector(_nentries); + _y = std::vector(_nentries); + for (int i=0;i<_nentries;i++) + f2->GetRandom2(_x.at(i),_y.at(i)); + delete f2; } static Double_t g22(Double_t *x, Double_t *par) { @@ -922,15 +945,14 @@ public: return result; } - TH2F *_h2; - TF2 *f2; Int_t _nentries = 100000; Int_t _npar = 15; + std::vector _x, _y; }; fit2_e gfit2; -void run_experiments(const int &n=1, - const int &lscaling=0) +void cmaesFullBench(const int &n=10, + const int &lscaling=1) { std::cout << "Proceeding with " << n << " runs on every problems\n"; if (lscaling > 0) @@ -952,42 +974,42 @@ void run_experiments(const int &n=1, int cn = 0; std::map::iterator mit = mexperiments.begin(); while(mit!=mexperiments.end()) - { - for (int i=0;iset_lambda(lambdas.at(j)); - else - { - (*mit).second->set_lambda(-1); - (*mit).second->set_restarts(4); - fitter_name = "aipop"; - } - (*mit).second->set_lscaling(lscaling); - (*mit).second->Setup(); - if (i == 0) - { - acmaes_stats.push_back((*mit).second->_ef(fitter_name));//_l"+std::to_string(lambdas.at(j)))); - } - else - { - acmaes_stats.at(cn*(lambdas.size())+j).merge((*mit).second->_ef(fitter_name));//_l"+std::to_string(lambdas.at(j)))); - } - (*mit).second->Cleanup(); - } - (*mit).second->set_lambda(-1); // N/A to Minuit2 - (*mit).second->Setup(); - if (i == 0) - minuit2_stats.push_back((*mit).second->_ef("Minuit2")); - else minuit2_stats.back().merge((*mit).second->_ef("Minuit2")); - (*mit).second->Cleanup(); - } - ++cn; - ++mit; - } + { + std::cout << "Running " << (*mit).first << std::endl; + for (int i=0;iSetup(); + for (int j=0;j<(int)lambdas.size();j++) + { + std::string fitter_name = "acmaes"; + if (lambdas.at(j) != -2) + (*mit).second->set_lambda(lambdas.at(j)); + else + { + (*mit).second->set_lambda(-1); + (*mit).second->set_restarts(4); + fitter_name = "aipop"; + } + (*mit).second->set_lscaling(lscaling); + + if (i == 0) + { + acmaes_stats.push_back((*mit).second->_ef(fitter_name)); + } + else + { + acmaes_stats.at(cn*(lambdas.size())+j).merge((*mit).second->_ef(fitter_name)); + } + } + (*mit).second->set_lambda(-1); // N/A to Minuit2 + if (i == 0) + minuit2_stats.push_back((*mit).second->_ef("Minuit2")); + else minuit2_stats.back().merge((*mit).second->_ef("Minuit2")); + (*mit).second->Cleanup(); + } + ++cn; + ++mit; + } std::cout << "nexp=" << nexp << " / stats size=" << acmaes_stats.size() << std::endl; From 1d200ef0139e1c5fc03c6b285e5da61aef89e4e6 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 9 Sep 2014 14:49:32 +0200 Subject: [PATCH 66/98] updated cmaes due to new setters/getters in libcmaes --- math/cmaes/src/CMAESMinimizer.cxx | 50 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 4163da89ac18d..3adaed9e4145c 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -349,10 +349,10 @@ namespace ROOT const std::string &fplot, const bool &withnumgradient) { - cmaparams._algo = fMinimizer; + cmaparams.set_algo(fMinimizer); if (gDebug > 0) - cmaparams._quiet = false; - else cmaparams._quiet = true; + cmaparams.set_quiet(false); + else cmaparams.set_quiet(true); for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) cmaparams.set_fixed_p((*mit).first,(*mit).second); cmaparams.set_edm(true); // always activate EDM computation. @@ -365,8 +365,8 @@ namespace ROOT cmaparams.set_restarts(nrestarts); if (ftarget > 0.0) cmaparams.set_ftarget(ftarget); - cmaparams._fplot = fplot; - cmaparams._with_gradient = withnumgradient; + cmaparams.set_fplot(fplot); + cmaparams.set_gradient(withnumgradient); } bool TCMAESMinimizer::Minimize() @@ -505,20 +505,20 @@ namespace ROOT fCMAparams = cmaparams; } } - Info("CMAESMinimizer","optimization status=%i",fCMAsols._run_status); - if (fCMAsols._edm > 10*Tolerance()) // XXX: max edm seems to be left to each minimizer's internal implementation... + Info("CMAESMinimizer","optimization status=%i",fCMAsols.run_status()); + if (fCMAsols.edm() > 10*Tolerance()) // XXX: max edm seems to be left to each minimizer's internal implementation... fStatus = 3; - else if (fCMAsols._run_status == 0 || fCMAsols._run_status == 1) + else if (fCMAsols.run_status() == 0 || fCMAsols.run_status() == 1) fStatus = 0; - else if (fCMAsols._run_status == 7 || fCMAsols._run_status == 9) + else if (fCMAsols.run_status() == 7 || fCMAsols.run_status() == 9) fStatus = 4; // reached budget limit. else fStatus = 5; - return fCMAsols._run_status >= 0; // above 0 are partial successes at worst. + return fCMAsols.run_status() >= 0; // above 0 are partial successes at worst. } double TCMAESMinimizer::MinValue() const { - return fCMAsols.best_candidate()._fvalue; + return fCMAsols.best_candidate().get_fvalue(); } const double* TCMAESMinimizer::X() const @@ -530,13 +530,13 @@ namespace ROOT if (fWithLinearScaling) { if (fWithBounds) - x = bc.get_x_pheno>(fCMAparams_lb); - else x = bc.get_x_pheno>(fCMAparams_l); + x = bc.get_x_pheno_dvec>(fCMAparams_lb); + else x = bc.get_x_pheno_dvec>(fCMAparams_l); } else { if (fWithBounds) - x = bc.get_x_pheno>(fCMAparams_b); + x = bc.get_x_pheno_dvec>(fCMAparams_b); else x = bc.get_x_dvec(); } for (int i=0;i 0.0) fGlobalCC.push_back(0.0); else fGlobalCC.push_back(std::sqrt(1.0 - 1.0/denom)); From 6c06502f0e2ec88ee0a2cae037061309fc245d97 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 9 Sep 2014 15:24:38 +0200 Subject: [PATCH 67/98] merge with stash --- hist/hist/src/TF1.cxx | 2 +- math/cmaes/src/CMAESMinimizer.cxx | 7 ++++ math/cmaes/test/cmaesFullBench.py | 10 ++--- math/mathcore/src/FitConfig.cxx | 8 +++- math/minuit2/src/Minuit2Minimizer.cxx | 2 +- tutorials/fit/Ifit.C | 4 +- tutorials/fit/cmaesFullBench.C | 54 +++++++++++++++------------ tutorials/fit/minuit2GausFit.C | 2 +- 8 files changed, 56 insertions(+), 33 deletions(-) diff --git a/hist/hist/src/TF1.cxx b/hist/hist/src/TF1.cxx index a78c701afdd5d..9a0d51f71db9e 100644 --- a/hist/hist/src/TF1.cxx +++ b/hist/hist/src/TF1.cxx @@ -1544,7 +1544,7 @@ Double_t TF1::GetMinMaxNDim(Double_t * x , bool findmax, Double_t epsilon, Int_t stepSize = (rmax[i] - rmin[i])/100; else if (std::abs(x[i]) > 1.) stepSize = 0.1*x[i]; - + // set variable names if (ndim <= 3) { if (i == 0) { diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 3adaed9e4145c..37305f086eb9c 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -128,6 +128,8 @@ namespace ROOT bool TCMAESMinimizer::SetVariable(unsigned int ivar, const std::string & name, double val, double step) { + std::cout << " add parameter " << name << " " << val << " step " << step << std::endl; + if (ivar > fInitialX.size() ) { MATH_ERROR_MSG("TCMAESMinimizer::SetVariable","ivar out of range"); return false; @@ -423,6 +425,11 @@ namespace ROOT std::cout << std::endl; }*/ //debug + + std::cout << "initial sigmas="; + for (int i=0;iFill( _x.at(i) ); h1bis->Fill( _x.at(i) ); } + delete ((TF1 *)(gROOT->GetFunction("gaus"))); TStopwatch timer; timer.Start(); - TFitResultPtr r1 = h1->Fit("gaus","S0"); + TFitResultPtr r1 = h1->Fit("gaus","VS0"); timer.Stop(); Double_t cputime1 = timer.CpuTime(); + delete ((TF1 *)(gROOT->GetFunction("gaus"))); TStopwatch timer2; timer2.Start(); - TFitResultPtr r2 = h1bis->Fit("gaus","LS0"); + TFitResultPtr r2 = h1bis->Fit("gaus","VLS0"); timer2.Stop(); Double_t cputime2 = timer2.CpuTime(); @@ -284,11 +286,11 @@ public: histo->Fill(_xs.at(pass).at(j)); mhisto->Fill(_xs.at(pass).at(j)); } - timer.Start(); - TFitResultPtr r = histo->Fit(fitFcn,"QS0"); // from TH1.cxx: Q: quiet, 0: do not plot + /*timer.Start(); + TFitResultPtr r = histo->Fit(fitFcn,"VS0"); // from TH1.cxx: Q: quiet, 0: do not plot timer.Stop(); Double_t cputime = timer.CpuTime(); - stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls());*/ delete histo; delete fitFcn; } @@ -296,7 +298,7 @@ public: timer.Start(); TF1 *fitFcn = new TF1("fitFcn",lorentz_fit_e::fitFunction,0,3,6); fitFcn->SetParameters(1,1,1,6,.03,1); - TFitResultPtr r = mhisto->Fit(fitFcn,"QS0"); + TFitResultPtr r = mhisto->Fit(fitFcn,"VS0"); timer.Stop(); double cputime = timer.CpuTime(); stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); @@ -375,7 +377,7 @@ public: fitFcn->SetParameters(100,0,0,2,7); fitFcn->Update(); timer.Start(); - TFitResultPtr r = _histo->Fit("fitFcn","S0"); + TFitResultPtr r = _histo->Fit("fitFcn","VS0"); timer.Stop(); Double_t cputime = timer.CpuTime(); printf("%s : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),timer.RealTime(),cputime); @@ -562,12 +564,12 @@ public: TStopwatch timer; timer.Start(); TVirtualFitter::SetDefaultFitter(fitter.c_str()); - TFitResultPtr r1 = h1->Fit(func1,"S0"); + TFitResultPtr r1 = h1->Fit(func1,"VS0"); timer.Stop(); Double_t cputime1 = timer.CpuTime(); TStopwatch timer2; timer2.Start(); - TFitResultPtr r2 = h2->Fit(func2,"S0"); + TFitResultPtr r2 = h2->Fit(func2,"VS0"); timer2.Stop(); Double_t cputime2 = timer2.CpuTime(); expstats stats("fit2dhist",r1->NTotalParameters(),_lambda); @@ -903,7 +905,7 @@ public: //Fit h2 with original function f2 TStopwatch timer; timer.Start(); - TFitResultPtr r = h2->Fit("f2","S0"); + TFitResultPtr r = h2->Fit("f2","VS0"); timer.Stop(); Double_t cputime = timer.CpuTime(); expstats stats("fit2",r->NTotalParameters(),_lambda); @@ -951,25 +953,25 @@ public: }; fit2_e gfit2; -void cmaesFullBench(const int &n=10, +void cmaesFullBench(const int &n=100, const int &lscaling=1) { std::cout << "Proceeding with " << n << " runs on every problems\n"; if (lscaling > 0) std::cout << "Linear scaling of parameters in ON\n"; //std::vector lambdas = {-1, 5, 10, 20, 40, 80, 160, 320, 640, 1280}; - std::vector lambdas = {-1, 50, 200, -2}; + std::vector lambdas = {-1, 50, 200, -2, -3}; std::vector acmaes_stats; std::vector minuit2_stats; std::map mexperiments; - mexperiments.insert(std::pair(ggauss_fit._name,&ggauss_fit)); + //mexperiments.insert(std::pair(ggauss_fit._name,&ggauss_fit)); mexperiments.insert(std::pair(glorentz_fit._name,&glorentz_fit)); - mexperiments.insert(std::pair(gfit2._name,&gfit2)); + /*mexperiments.insert(std::pair(gfit2._name,&gfit2)); mexperiments.insert(std::pair(ggauss2D_fit._name,&ggauss2D_fit)); mexperiments.insert(std::pair(gfit2a._name,&gfit2a)); mexperiments.insert(std::pair(gfit2dhist._name,&gfit2dhist)); mexperiments.insert(std::pair(gcombined_fit._name,&gcombined_fit)); - mexperiments.insert(std::pair(gex3d._name,&gex3d)); + mexperiments.insert(std::pair(gex3d._name,&gex3d));*/ int nexp = mexperiments.size(); int cn = 0; std::map::iterator mit = mexperiments.begin(); @@ -982,14 +984,20 @@ void cmaesFullBench(const int &n=10, for (int j=0;j<(int)lambdas.size();j++) { std::string fitter_name = "acmaes"; - if (lambdas.at(j) != -2) + if (lambdas.at(j) >= -1) (*mit).second->set_lambda(lambdas.at(j)); - else + else if (lambdas.at(j) == -2) { (*mit).second->set_lambda(-1); (*mit).second->set_restarts(4); fitter_name = "aipop"; } + else if (lambdas.at(j) == -3) + { + (*mit).second->set_lambda(-1); + (*mit).second->set_restarts(10); + fitter_name = "abipop"; + } (*mit).second->set_lscaling(lscaling); if (i == 0) @@ -1023,7 +1031,7 @@ void cmaesFullBench(const int &n=10, acmaes_stats.at(k).print_diff(std::cout); acmaes_stats.at(k).print_avg_to_file(); } - minuit2_stats.at(i).diff(acmaes_stats.at(i*lambdas.size())); + minuit2_stats.at(i).diff(acmaes_stats.at(i*lambdas.size()+lambdas.size()-1)); minuit2_stats.at(i).print_avg_to_file(); } } diff --git a/tutorials/fit/minuit2GausFit.C b/tutorials/fit/minuit2GausFit.C index 0a63246a63725..758fddbfd0254 100644 --- a/tutorials/fit/minuit2GausFit.C +++ b/tutorials/fit/minuit2GausFit.C @@ -54,7 +54,7 @@ void testGausFit( std::string type = "Minuit2", int n = 1000) { c1->cd(1); cout << "\nDo Fit 1\n"; - h1->Fit("gaus","Q"); + h1->Fit("gaus","V"); h1->Draw(); c1->cd(2); cout << "\nDo Fit 2\n"; From 237b7387b1e3bdb0c14e462d06a25c2ff0e275ba Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 9 Sep 2014 15:27:11 +0200 Subject: [PATCH 68/98] fixed previous commit --- math/cmaes/src/CMAESMinimizer.cxx | 7 ------- math/mathcore/src/FitConfig.cxx | 8 +------- math/minuit2/src/Minuit2Minimizer.cxx | 2 +- tutorials/fit/Ifit.C | 5 +---- 4 files changed, 3 insertions(+), 19 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 37305f086eb9c..09242c887947f 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -128,8 +128,6 @@ namespace ROOT bool TCMAESMinimizer::SetVariable(unsigned int ivar, const std::string & name, double val, double step) { - std::cout << " add parameter " << name << " " << val << " step " << step << std::endl; - if (ivar > fInitialX.size() ) { MATH_ERROR_MSG("TCMAESMinimizer::SetVariable","ivar out of range"); return false; @@ -426,11 +424,6 @@ namespace ROOT }*/ //debug - std::cout << "initial sigmas="; - for (int i=0;iGetValue("lscaling",fWithLinearScaling); cmaesOpt->GetValue("numgradient",withnumgradient); + cmaesOpt->GetValue("mt_feval",mtfeval); } if (gDebug > 0) { - std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0scaled << " / lambda=" << lambda << " / fTol=" << Tolerance() << " / with_bounds=" << fWithBounds << " / with_gradient=" << fWithGradient << " / linear_scaling=" << fWithLinearScaling << " / maxiter=" << maxiter << " / maxfevals=" << maxfevals << std::endl; + std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0scaled << " / lambda=" << lambda << " / fTol=" << Tolerance() << " / with_bounds=" << fWithBounds << " / with_gradient=" << fWithGradient << " / linear_scaling=" << fWithLinearScaling << " / maxiter=" << maxiter << " / maxfevals=" << maxfevals << " / mtfeval=" << mtfeval << std::endl; std::cout << "x0="; std::copy(fInitialX.begin(),fInitialX.end(),std::ostream_iterator(std::cout," ")); std::cout << std::endl; @@ -472,7 +476,7 @@ namespace ROOT //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_lb = cmaparams; } @@ -481,7 +485,7 @@ namespace ROOT //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(vscaling,vshift); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_l = cmaparams; } @@ -493,14 +497,14 @@ namespace ROOT Info("CMAESMinimizer","Minimizing with bounds"); GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_b = cmaparams; } else { CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams = cmaparams; } From 2ccbd83628c2feab315b986a8c0a372567082cc0 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Thu, 18 Sep 2014 09:31:53 +0200 Subject: [PATCH 71/98] added support for control of the quiet option of libcmaes through Minimizer's options --- math/cmaes/inc/CMAESMinimizer.h | 3 ++- math/cmaes/src/CMAESMinimizer.cxx | 15 +++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 53570fa78ec87..98b96d2ee22d5 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -124,7 +124,8 @@ namespace ROOT const double &ftarget, const std::string &fplot, const bool &withnumgradient, - const bool &mtfeval); + const bool &mtfeval, + const bool &quiet); /** method to perform the minimization. diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index f42d6a05ca1e6..7f5a7d117e821 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -348,10 +348,11 @@ namespace ROOT const double &ftarget, const std::string &fplot, const bool &withnumgradient, - const bool &mtfeval) + const bool &mtfeval, + const bool &quiet) { cmaparams.set_algo(fMinimizer); - if (gDebug > 0) + if (gDebug > 0 || !quiet) cmaparams.set_quiet(false); else cmaparams.set_quiet(true); for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) @@ -445,6 +446,7 @@ namespace ROOT std::string fplot; int withnumgradient = 0; // whether to use numerical gradient injection. int mtfeval = 0; // parallel execution of objective function + int quiet = 0; // set hyper-parameters according to IOptions object. if (cmaesOpt) @@ -458,6 +460,7 @@ namespace ROOT cmaesOpt->GetValue("lscaling",fWithLinearScaling); cmaesOpt->GetValue("numgradient",withnumgradient); cmaesOpt->GetValue("mt_feval",mtfeval); + cmaesOpt->GetValue("quiet",quiet); } if (gDebug > 0) @@ -476,7 +479,7 @@ namespace ROOT //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_lb = cmaparams; } @@ -485,7 +488,7 @@ namespace ROOT //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(vscaling,vshift); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_l = cmaparams; } @@ -497,14 +500,14 @@ namespace ROOT Info("CMAESMinimizer","Minimizing with bounds"); GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_b = cmaparams; } else { CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams = cmaparams; } From f20103e9c030709fddfa6e0333df4e4d74a8ea75 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Thu, 18 Sep 2014 15:39:02 +0200 Subject: [PATCH 72/98] cmaes: added support for seed as an option + added example of a custom progress function --- math/cmaes/src/CMAESMinimizer.cxx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 7f5a7d117e821..7fb4f8288128d 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -402,7 +402,7 @@ namespace ROOT std::cout << std::endl;*/ return (*fObjFunc)(x); }; - + // gradient function. //std::cout << "fWithGradient=" << fWithGradient << std::endl; GradFunc gfit = nullptr; @@ -447,6 +447,7 @@ namespace ROOT int withnumgradient = 0; // whether to use numerical gradient injection. int mtfeval = 0; // parallel execution of objective function int quiet = 0; + int seed = 0; // set hyper-parameters according to IOptions object. if (cmaesOpt) @@ -461,6 +462,7 @@ namespace ROOT cmaesOpt->GetValue("numgradient",withnumgradient); cmaesOpt->GetValue("mt_feval",mtfeval); cmaesOpt->GetValue("quiet",quiet); + cmaesOpt->GetValue("seed",seed); } if (gDebug > 0) @@ -476,9 +478,14 @@ namespace ROOT if (fWithBounds) { Info("CMAESMinimizer","Minimizing with bounds"); - //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; + /*ProgressFunc>,CMASolutions> pfunc = [](const CMAParameters> &cmaparams, const CMASolutions &cmasols) + { + std::cout << "iter=" << cmasols.niter() << " / evals=" << cmasols.nevals() << " / f-value=" << cmasols.best_candidate().get_fvalue() << " / sigma=" << cmasols.sigma() << std::endl; + std::cout << "best x=" << cmaparams.get_gp().pheno(cmasols.best_candidate().get_x_dvec()).transpose() << std::endl; + return 0; + };*/ GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); - CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_lb = cmaparams; @@ -487,7 +494,7 @@ namespace ROOT { //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; GenoPheno gp(vscaling,vshift); - CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_l = cmaparams; @@ -499,14 +506,14 @@ namespace ROOT { Info("CMAESMinimizer","Minimizing with bounds"); GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); - CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0,gp); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams_b = cmaparams; } else { - CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,0); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed); SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); fCMAsols = libcmaes::cmaes>(ffit,cmaparams); fCMAparams = cmaparams; From 54e1585fbf77f0297ea08b2b52022a6ef6dcc258 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 19 Sep 2014 07:52:25 +0200 Subject: [PATCH 73/98] cmaes: fixed activation of gradient function when available from within ROOT --- math/cmaes/src/CMAESMinimizer.cxx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 7fb4f8288128d..3867e98df511c 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -477,7 +477,7 @@ namespace ROOT { if (fWithBounds) { - Info("CMAESMinimizer","Minimizing with bounds"); + Info("CMAESMinimizer","Minimizing with bounds and linear scaling"); /*ProgressFunc>,CMASolutions> pfunc = [](const CMAParameters> &cmaparams, const CMASolutions &cmasols) { std::cout << "iter=" << cmasols.niter() << " / evals=" << cmasols.nevals() << " / f-value=" << cmasols.best_candidate().get_fvalue() << " / sigma=" << cmasols.sigma() << std::endl; @@ -487,16 +487,17 @@ namespace ROOT GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); - fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); fCMAparams_lb = cmaparams; } else { //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; + Info("CMAESMinimizer","Minimizing with linear scaling"); GenoPheno gp(vscaling,vshift); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); - fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); fCMAparams_l = cmaparams; } } @@ -508,14 +509,15 @@ namespace ROOT GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); - fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); fCMAparams_b = cmaparams; } else { + Info("CMAESMinimizer","Minimizing without bounds or linear scaling"); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed); SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); - fCMAsols = libcmaes::cmaes>(ffit,cmaparams); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); fCMAparams = cmaparams; } } From 8dd3211f7374d22924dacd0bc1de0d8a193a46b7 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Sat, 8 Nov 2014 11:46:16 +0100 Subject: [PATCH 74/98] fix wrt to cmaes API --- math/cmaes/src/CMAESMinimizer.cxx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 3867e98df511c..80d0e60b7a852 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -72,8 +72,6 @@ namespace ROOT fMinimizer = sepIPOP_CMAES; else if (algoname == "sepbipop") fMinimizer = sepBIPOP_CMAES; - - } TCMAESMinimizer::TCMAESMinimizer(const TCMAESMinimizer &m) @@ -649,12 +647,10 @@ namespace ROOT { if (!fWithBounds) { - fCMAparams_l.set_automaxiter(true); le = errstats>::profile_likelihood(ffit,fCMAparams_l,fCMAsols,i,false,samplesize,ErrorDef()); } else { - fCMAparams_lb.set_automaxiter(true); le = errstats>::profile_likelihood(ffit,fCMAparams_lb,fCMAsols,i,false,samplesize); } } @@ -662,12 +658,10 @@ namespace ROOT { if (!fWithBounds) { - fCMAparams_l.set_automaxiter(true); le = errstats>::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize,ErrorDef()); } else { - fCMAparams_lb.set_automaxiter(true); le = errstats>::profile_likelihood(ffit,fCMAparams_b,fCMAsols,i,false,samplesize); } } From 3f6f5ed9bc44ccc83fb81e0f14056e23e91b29d9 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 10 Nov 2014 12:47:16 +0000 Subject: [PATCH 75/98] cmaes working with cmake --- cmake/modules/RootBuildOptions.cmake | 3 +-- cmake/modules/SearchInstalledSoftware.cmake | 14 ++++++++++++++ math/cmaes/CMakeLists.txt | 7 +++++-- math/cmaes/Module.mk | 8 +++++--- math/cmaes/test/CMakeLists.txt | 6 +++--- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/cmake/modules/RootBuildOptions.cmake b/cmake/modules/RootBuildOptions.cmake index d8e646d5ce1eb..ff67ee0081d42 100644 --- a/cmake/modules/RootBuildOptions.cmake +++ b/cmake/modules/RootBuildOptions.cmake @@ -114,7 +114,6 @@ ROOT_BUILD_OPTION(castor ON "CASTOR support, requires libshift from CASTOR >= 1. ROOT_BUILD_OPTION(chirp ON "Chirp support (Condor remote I/O), requires libchirp_client") ROOT_BUILD_OPTION(clarens ON "Clarens RPC support, optionally used by PROOF") ROOT_BUILD_OPTION(cling ON "Enable new CLING C++ interpreter") -ROOT_BUILD_OPTION(cmaes ON "Build the libcmaes minimizer library wrapper") ROOT_BUILD_OPTION(cocoa ${cocoa_defvalue} "Use native Cocoa/Quartz graphics backend (MacOS X only)") ROOT_BUILD_OPTION(davix ${davix_defvalue} "DavIx library for HTTP/WEBDAV access") ROOT_BUILD_OPTION(dcache ON "dCache support, requires libdcap from DESY") @@ -138,7 +137,7 @@ ROOT_BUILD_OPTION(krb5 ON "Kerberos5 support, requires Kerberos libs") ROOT_BUILD_OPTION(ldap ON "LDAP support, requires (Open)LDAP libs") ROOT_BUILD_OPTION(mathmore ON "Build the new libMathMore extended math library, requires GSL (vers. >= 1.8)") ROOT_BUILD_OPTION(memstat ${memstat_defvalue} "A memory statistics utility, helps to detect memory leaks") -ROOT_BUILD_OPTION(cmaes ON "Build the libcmaes minimizer library wrapper") +ROOT_BUILD_OPTION(libcmaes ON "Build the libcmaes minimizer library") ROOT_BUILD_OPTION(minuit2 ${minuit2_defvalue} "Build the new libMinuit2 minimizer library") ROOT_BUILD_OPTION(monalisa ON "Monalisa monitoring support, requires libapmoncpp") ROOT_BUILD_OPTION(mysql ON "MySQL support, requires libmysqlclient") diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index ed9970a66461a..2a8d4ba1a85fd 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -471,6 +471,20 @@ if(sqlite) endif() endif() +#---Check for Libcmaes------------------------------------------------------------------- +if(libcmaes) + message(STATUS "Looking for libcmaes") + find_package(LibCmaes) + if(NOT LIBCMAES_FOUND) + if(fail-on-missing) + message(FATAL_ERROR "libcmaes not found") + else() + message(STATUS "libcmaes not found. Switching off libcmaes option") + set(libcmaes OFF CACHE BOOL "" FORCE) + endif() + endif() +endif() + #---Check for Pythia6------------------------------------------------------------------- if(pythia6) message(STATUS "Looking for Pythia6") diff --git a/math/cmaes/CMakeLists.txt b/math/cmaes/CMakeLists.txt index 5efa39df31e14..50316c11729c1 100644 --- a/math/cmaes/CMakeLists.txt +++ b/math/cmaes/CMakeLists.txt @@ -7,7 +7,10 @@ ROOT_USE_PACKAGE(hist/hist) add_definitions(-DWARNINGMSG -DUSE_ROOT_ERROR) -ROOT_GENERATE_DICTIONARY(G__cmaes *.h cmaes/*.h MODULE cmaes LINKDEF LinkDef.h) +include_directories(${LIBCMAES_INCLUDE_DIR}) +link_directories(${LIBCMAES_LIBRARIES}) -ROOT_LINKER_LIBRARY(cmaes *.cxx G__cmaes.cxx DEPENDENCIES MathCore Hist) +ROOT_GENERATE_DICTIONARY(G__cmaes *.h MODULE cmaes LINKDEF LinkDef.h) + +ROOT_LINKER_LIBRARY(cmaes_root *.cxx G__cmaes.cxx DEPENDENCIES MathCore Hist LIBRARIES cmaes) ROOT_INSTALL_HEADERS() \ No newline at end of file diff --git a/math/cmaes/Module.mk b/math/cmaes/Module.mk index 1f6c8f5724264..df641e9ab8cc6 100644 --- a/math/cmaes/Module.mk +++ b/math/cmaes/Module.mk @@ -1,4 +1,4 @@ -# Module.ml for cmaes module. +# Module.mk for cmaes module. MODNAME := cmaes MODDIR := $(ROOT_SRCDIR)/math/$(MODNAME) @@ -10,6 +10,8 @@ CMAESDIRS := $(CMAESDIR)/src CMAESDIRI := $(CMAESDIR)/inc #CMAESDIRT :=$(call stripsrc,$(CMAESDIR)/test) +CMAESINCDIR := $(LIBCMAES_INCLUDE_DIR) + CMAESBASEVERS := cmaes-1_0_0 CMAESBASESRCS := $(MODDIRS)/$(CMAESBASEVERS).tar.gz CMAESBASEDIRS := $(MODDIRS)/$(CMAESBASEVERS) @@ -79,7 +81,7 @@ $(CMAESLIB): $(CMAESO) $(CMAESDO) $(ORDER_) $(MAINLIBS) $(CMAESLIBDEP) "$(SOFLAGS)" libcmaesroot.$(SOEXT) $@ \ "$(CMAESO) $(CMAESDO)" "-lcmaes -lMathCore" "$(CMAESLIBEXTRA)" -$(call pcmrule,MINUIT2) +$(call pcmrule,CMAES) $(noop) $(CMAESDS): $(CMAESH) $(CMAESL) $(ROOTCLINGEXE) $(call pcmdep,CMAES) @@ -127,7 +129,7 @@ $(CMAESDO): CXXFLAGS += -DWARNINGMSG -DUSE_ROOT_ERROR #ifneq ($(USE_OPENMP),) #$(CMAESO): CXXFLAGS += -DCMAES_THREAD_SAFE -DCMAES_PARALLEL_OPENMP #math/cmaes/src/Numerical2PGradientCalculator.o: -$(CMAESO):CXXFLAGS += -D_GLIBCXX_PARALLEL -fopenmp +$(CMAESO):CXXFLAGS += -D_GLIBCXX_PARALLEL -fopenmp $(CMAESDO):CXXFLAGS += -D_GLIBCXX_PARALLEL -fopenmp $(CMAESLIB):LDFLAGS += -fopenmp #endif diff --git a/math/cmaes/test/CMakeLists.txt b/math/cmaes/test/CMakeLists.txt index 2b1401083af05..e41053d5999d0 100644 --- a/math/cmaes/test/CMakeLists.txt +++ b/math/cmaes/test/CMakeLists.txt @@ -1,4 +1,4 @@ -project(minuit2-tests) +project(cmaes-tests) find_package(ROOT REQUIRED) include(${ROOT_USE_FILE}) @@ -30,10 +30,10 @@ set(TestSourceMnSim -#---For the simple Minuit2 tests build and defined them--------------- +#---For the simple cmaes tests build and defined them--------------- foreach(file ${TestSourceMnTutorial}) get_filename_component(testname ${file} NAME_WE) - ROOT_EXECUTABLE(${testname} ${file} LIBRARIES Minuit2) + ROOT_EXECUTABLE(${testname} ${file} LIBRARIES cmaes) ROOT_ADD_TEST(minuit2-${testname} COMMAND ${testname}) endforeach() From a9c69e25b7c6668590da2a84d61abcbc94280191 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 10 Nov 2014 16:17:32 +0000 Subject: [PATCH 76/98] fixes for cmake and configure building systems with cmaes --- etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C | 2 +- math/cmaes/Module.mk | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C b/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C index 25bbcf863826e..161ffdc5a3b8e 100644 --- a/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C +++ b/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C @@ -1,5 +1,5 @@ void P090_TCMAESMinimizer() { gPluginMgr->AddHandler("ROOT::Math::Minimizer", "cmaes", "ROOT::cmaes::TCMAESMinimizer", - "cmaesroot", "TCMAESMinimizer(const char *)"); + "cmaes_root", "TCMAESMinimizer(const char *)"); } diff --git a/math/cmaes/Module.mk b/math/cmaes/Module.mk index df641e9ab8cc6..e5c19d24a402d 100644 --- a/math/cmaes/Module.mk +++ b/math/cmaes/Module.mk @@ -10,8 +10,6 @@ CMAESDIRS := $(CMAESDIR)/src CMAESDIRI := $(CMAESDIR)/inc #CMAESDIRT :=$(call stripsrc,$(CMAESDIR)/test) -CMAESINCDIR := $(LIBCMAES_INCLUDE_DIR) - CMAESBASEVERS := cmaes-1_0_0 CMAESBASESRCS := $(MODDIRS)/$(CMAESBASEVERS).tar.gz CMAESBASEDIRS := $(MODDIRS)/$(CMAESBASEVERS) @@ -47,7 +45,7 @@ CMAESO := $(call stripsrc,$(CMAESS:.cxx=.o)) CMAESDEP := $(CMAESO:.o=.d) $(CMAESDO:.o=.d) -CMAESLIB := $(LPATH)/libcmaesroot.$(SOEXT) +CMAESLIB := $(LPATH)/libcmaes_root.$(SOEXT) CMAESMAP := $(CMAESLIB:.$(SOEXT)=.rootmap) # use this compiler option if want to optimize object allocation in cmaes @@ -78,7 +76,7 @@ include/%.h: $(CMAESDIRI)/%.h $(CMAESLIB): $(CMAESO) $(CMAESDO) $(ORDER_) $(MAINLIBS) $(CMAESLIBDEP) @$(MAKELIB) $(PLATFORM) $(LD) "$(LDFLAGS)" \ - "$(SOFLAGS)" libcmaesroot.$(SOEXT) $@ \ + "$(SOFLAGS)" libcmaes_root.$(SOEXT) $@ \ "$(CMAESO) $(CMAESDO)" "-lcmaes -lMathCore" "$(CMAESLIBEXTRA)" $(call pcmrule,CMAES) From 8f51b6aea3b3dfd3452eb8426ec800f2b32208ea Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Wed, 12 Nov 2014 12:58:40 +0000 Subject: [PATCH 77/98] fix for new cmaes pli accesors --- math/cmaes/src/CMAESMinimizer.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 80d0e60b7a852..75f563a971aa4 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -665,8 +665,8 @@ namespace ROOT le = errstats>::profile_likelihood(ffit,fCMAparams_b,fCMAsols,i,false,samplesize); } } - errLow = le.getErrMin(); - errUp = le.getErrMax(); + errLow = le.get_err_min(); + errUp = le.get_err_max(); return true; } From 276f559511df3fc9ee0348f5801d8f47a86e9ed9 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 18 Nov 2014 08:13:45 +0000 Subject: [PATCH 78/98] Support for CMA-ES minimizer based on libcmaes On-par or better than Minuit2 on most tested problems. Support includes RooFit. --- Makefile | 10 +- cmake/modules/FindLibCmaes.cmake | 51 + cmake/modules/FindLibCmaes.cmake~ | 51 + cmake/modules/RootBuildOptions.cmake | 1 + cmake/modules/SearchInstalledSoftware.cmake | 14 + config/Makefile.depend | 4 + config/Makefile.in | 5 + configure | 26 + core/base/src/TPluginManager.cxx | 8 +- .../P010_Minuit2Minimizer.C | 4 +- .../P090_TCMAESMinimizer.C | 5 + graf2d/asimage/src/libAfterImage/asfont.c | 6 +- hist/hist/src/TF1.cxx | 2 +- math/CMakeLists.txt | 1 + math/cmaes/CMakeLists.txt | 16 + math/cmaes/Module.mk | 140 +++ math/cmaes/inc/CMAESMinimizer.h | 313 +++++ math/cmaes/inc/LinkDef.h | 30 + math/cmaes/src/CMAESMinimizer.cxx | 705 +++++++++++ math/cmaes/test/CMakeLists.txt | 66 ++ math/cmaes/test/Makefile | 90 ++ math/cmaes/test/cmaesFullBench.py | 104 ++ math/cmaes/test/testMinimizer.cxx | 891 ++++++++++++++ math/cmaes/test/testNdimFit.cxx | 285 +++++ math/cmaes/test/testUnbinGausFit.cxx | 333 ++++++ math/cmaes/test/testUserFunc.cxx | 88 ++ math/mathcore/src/Factory.cxx | 23 +- math/mathcore/src/FitConfig.cxx | 4 +- math/mathcore/src/MinimizerOptions.cxx | 7 + math/minuit2/src/Minuit2Minimizer.cxx | 2 +- tutorials/fit/Ifit.C | 4 +- tutorials/fit/cmaesFitBench.C | 139 +++ tutorials/fit/cmaesFitBench2D.C | 105 ++ tutorials/fit/cmaesFullBench.C | 1037 +++++++++++++++++ tutorials/fit/cmaesGausFit.C | 99 ++ tutorials/fit/cmaes_fit2a.C | 85 ++ tutorials/fit/cmaes_fit2dHist.C | 253 ++++ tutorials/fit/minuit2GausFit.C | 4 +- 38 files changed, 4988 insertions(+), 23 deletions(-) create mode 100644 cmake/modules/FindLibCmaes.cmake create mode 100644 cmake/modules/FindLibCmaes.cmake~ create mode 100644 etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C create mode 100644 math/cmaes/CMakeLists.txt create mode 100644 math/cmaes/Module.mk create mode 100644 math/cmaes/inc/CMAESMinimizer.h create mode 100644 math/cmaes/inc/LinkDef.h create mode 100644 math/cmaes/src/CMAESMinimizer.cxx create mode 100644 math/cmaes/test/CMakeLists.txt create mode 100644 math/cmaes/test/Makefile create mode 100644 math/cmaes/test/cmaesFullBench.py create mode 100644 math/cmaes/test/testMinimizer.cxx create mode 100644 math/cmaes/test/testNdimFit.cxx create mode 100644 math/cmaes/test/testUnbinGausFit.cxx create mode 100644 math/cmaes/test/testUserFunc.cxx create mode 100644 tutorials/fit/cmaesFitBench.C create mode 100644 tutorials/fit/cmaesFitBench2D.C create mode 100644 tutorials/fit/cmaesFullBench.C create mode 100644 tutorials/fit/cmaesGausFit.C create mode 100644 tutorials/fit/cmaes_fit2a.C create mode 100644 tutorials/fit/cmaes_fit2dHist.C diff --git a/Makefile b/Makefile index 7edf5e98f0a62..5f07b86e6be5b 100644 --- a/Makefile +++ b/Makefile @@ -82,7 +82,7 @@ MODULES = build interpreter/llvm interpreter/cling core/metautils \ io/io math/mathcore net/net core/zip core/lzma math/matrix \ core/newdelete hist/hist tree/tree graf2d/freetype \ graf2d/mathtext graf2d/graf graf2d/gpad graf3d/g3d \ - gui/gui math/minuit hist/histpainter tree/treeplayer \ + gui/gui math/minuit math/cmaes hist/histpainter tree/treeplayer \ gui/ged tree/treeviewer math/physics graf2d/postscript \ core/rint html montecarlo/eg \ geom/geom geom/geompainter montecarlo/vmc \ @@ -246,6 +246,12 @@ endif ifeq ($(BUILDMINUIT2),yes) MODULES += math/minuit2 endif +ifeq ($(BUILDCMAES),yes) +MODULES += math/cmaes +endif +ifeq ($(BUILDCMAES),yes) +MODULES += math/cmaes +endif ifeq ($(BUILDUNURAN),yes) MODULES += math/unuran endif @@ -327,7 +333,7 @@ MODULES += core/unix core/winnt graf2d/x11 graf2d/x11ttf \ sql/oracle io/xmlparser math/mathmore \ tmva math/genetic io/hdfs graf2d/fitsio roofit/roofitcore \ roofit/roofit roofit/roostats roofit/histfactory \ - math/minuit2 net/monalisa math/fftw sql/odbc math/unuran \ + math/minuit2 math/cmaes net/monalisa math/fftw sql/odbc math/unuran \ geom/geocad geom/gdml graf3d/eve net/glite misc/memstat \ math/genvector net/bonjour graf3d/gviz3d graf2d/gviz \ proof/proofbench proof/afdsmgrd graf2d/ios \ diff --git a/cmake/modules/FindLibCmaes.cmake b/cmake/modules/FindLibCmaes.cmake new file mode 100644 index 0000000000000..c5161900b3f6f --- /dev/null +++ b/cmake/modules/FindLibCmaes.cmake @@ -0,0 +1,51 @@ +# - Try to find libcmaes, https://github.com/beniz/libcmaes +# Once done this will define +# +# LIBCMAES_FOUND - system has libcmaes +# LIBCMES_INCLUDE_DIR - the libcmaes include directory +# LIBCMAES_LIBRARIES - Link these to use libcmaes +# LIBCMAES_DEFINITIONS - Compiler switches required for using libcmaes +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + + +# Copyright (c) 2014, Emmanuel Benazera, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if ( LIBCMAES_INCLUDE_DIR AND LIBCMAES_LIBRARIES ) + # in cache already + SET(Libcmaes_FIND_QUIETLY TRUE) +endif ( LIBCMAES_INCLUDE_DIR AND LIBCMAES_LIBRARIES ) + +# use pkg-config to get the directories and then use these values +# in the FIND_PATH() and FIND_LIBRARY() calls +if( NOT WIN32 ) + find_package(PkgConfig) + + pkg_check_modules(PC_LIBCMAES REQUIRED libcmaes) + + set(LIBCMAES_INCLUDE_DIR ${PC_LIBCMAES_INCLUDE_DIRS}) + set(LIBCMAES_LIBRARIES ${PC_LIBCMAES_LIBRARY_DIRS}) + set(LIBCMAES_DEFINITIONS ${PC_LIBCMAES_CFLAGS_OTHER}) +endif( NOT WIN32 ) + +find_path(LIBCMAES_INCLUDE_DIR NAMES cmaes.h + PATHS + ${PC_LIBCMAES_INCLUDEDIR} + ${PC_LIBCMAES_INCLUDE_DIRS} +) + +find_library(LIBCMAES_LIBRARIES NAMES libcmaes + PATHS + ${PC_LIBCMAES_LIBDIR} + ${PC_LIBCMAES_LIBRARY_DIRS} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Libcmaes DEFAULT_MSG LIBCMAES_INCLUDE_DIR LIBCMAES_LIBRARIES ) + +# show the LIBCMAES_INCLUDE_DIR and LIBCMAES_LIBRARIES variables only in the advanced view +mark_as_advanced(LIBCMAES_INCLUDE_DIR LIBCMAES_LIBRARIES ) diff --git a/cmake/modules/FindLibCmaes.cmake~ b/cmake/modules/FindLibCmaes.cmake~ new file mode 100644 index 0000000000000..dc152d40ca4ca --- /dev/null +++ b/cmake/modules/FindLibCmaes.cmake~ @@ -0,0 +1,51 @@ +# - Try to find libcmaes, https://github.com/beniz/libcmaes +# Once done this will define +# +# LIBCMAES_FOUND - system has libcmaes +# LIBCMES_INCLUDE_DIR - the libcmaes include directory +# LIBCMAES_LIBRARIES - Link these to use libcmaes +# LIBCMAES_DEFINITIONS - Compiler switches required for using libcmaes +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + + +# Copyright (c) 2014, Emmanuel Benazera, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if ( LIBCMAES_INCLUDE_DIR AND LIBCMAES_LIBRARIES ) + # in cache already + SET(Libcmaes_FIND_QUIETLY TRUE) +endif ( LIBCMAES_INCLUDE_DIR AND LIBCMAES_LIBRARIES ) + +# use pkg-config to get the directories and then use these values +# in the FIND_PATH() and FIND_LIBRARY() calls +if( NOT WIN32 ) + find_package(PkgConfig) + + pkg_check_modules(PC_LIBCMAES REQUIRED libcmaes) + + set(LIBCMAES_INCLUDE_DIRS ${PC_LIBCMAES_INCLUDE_DIRS}) + set(LIBCMAES_LIBRARIES ${PC_LIBCMAES_LIBRARIES_DIRS}) + set(LIBCMAES_DEFINITIONS ${PC_LIBCMAES_CFLAGS_OTHER}) +endif( NOT WIN32 ) + +find_path(LIBCMAES_INCLUDE_DIR NAMES cmaes.h + PATHS + ${PC_LIBCMAES_INCLUDEDIR} + ${PC_LIBCMAES_INCLUDE_DIRS} +) + +find_library(LIBCMAES_LIBRARIES NAMES libcmaes + PATHS + ${PC_LIBCMAES_LIBDIR} + ${PC_LIBCMAES_LIBRARY_DIRS} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Libcmaes DEFAULT_MSG LIBCMAES_INCLUDE_DIR LIBCMAES_LIBRARIES ) + +# show the LIBCMAES_INCLUDE_DIR and LIBCMAES_LIBRARIES variables only in the advanced view +mark_as_advanced(LIBCMAES_INCLUDE_DIR LIBCMAES_LIBRARIES ) diff --git a/cmake/modules/RootBuildOptions.cmake b/cmake/modules/RootBuildOptions.cmake index 81b6bf8a7708a..bea18d05d66ef 100644 --- a/cmake/modules/RootBuildOptions.cmake +++ b/cmake/modules/RootBuildOptions.cmake @@ -137,6 +137,7 @@ ROOT_BUILD_OPTION(krb5 ON "Kerberos5 support, requires Kerberos libs") ROOT_BUILD_OPTION(ldap ON "LDAP support, requires (Open)LDAP libs") ROOT_BUILD_OPTION(mathmore ON "Build the new libMathMore extended math library, requires GSL (vers. >= 1.8)") ROOT_BUILD_OPTION(memstat ${memstat_defvalue} "A memory statistics utility, helps to detect memory leaks") +ROOT_BUILD_OPTION(libcmaes ON "Build the libcmaes minimizer library") ROOT_BUILD_OPTION(minuit2 ${minuit2_defvalue} "Build the new libMinuit2 minimizer library") ROOT_BUILD_OPTION(monalisa ON "Monalisa monitoring support, requires libapmoncpp") ROOT_BUILD_OPTION(mysql ON "MySQL support, requires libmysqlclient") diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index ed9970a66461a..2a8d4ba1a85fd 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -471,6 +471,20 @@ if(sqlite) endif() endif() +#---Check for Libcmaes------------------------------------------------------------------- +if(libcmaes) + message(STATUS "Looking for libcmaes") + find_package(LibCmaes) + if(NOT LIBCMAES_FOUND) + if(fail-on-missing) + message(FATAL_ERROR "libcmaes not found") + else() + message(STATUS "libcmaes not found. Switching off libcmaes option") + set(libcmaes OFF CACHE BOOL "" FORCE) + endif() + endif() +endif() + #---Check for Pythia6------------------------------------------------------------------- if(pythia6) message(STATUS "Looking for Pythia6") diff --git a/config/Makefile.depend b/config/Makefile.depend index de003dd6f6483..40d2a4e57d0a2 100644 --- a/config/Makefile.depend +++ b/config/Makefile.depend @@ -27,6 +27,7 @@ HTMLLIBDEPM = $(GRAFLIB) $(THREADLIB) MATHMORELIBDEPM = $(MATHCORELIB) MINUITLIBDEPM = $(GRAFLIB) $(HISTLIB) $(MATRIXLIB) $(MATHCORELIB) MINUIT2LIBDEPM = $(GRAFLIB) $(HISTLIB) $(MATRIXLIB) $(MATHCORELIB) +CMAESLIBDEPM = $(GRAFLIB) $(HISTLIB) $(MATHCORELIB) FUMILILIBDEPM = $(GRAFLIB) $(HISTLIB) $(MATHCORELIB) TREELIBDEPM = $(NETLIB) $(IOLIB) $(THREADLIB) TREEPLAYERLIBDEPM = $(TREELIB) $(G3DLIB) $(GRAFLIB) $(HISTLIB) $(GPADLIB) \ @@ -166,6 +167,7 @@ SPECTRUMPAINTERLIBDEP = $(SPECTRUMPAINTERLIBDEPM) HTMLLIBDEP = $(HTMLLIBDEPM) MINUITLIBDEP = $(MINUITLIBDEPM) MINUIT2LIBDEP = $(MINUIT2LIBDEPM) +CMAESLIBDEP = $(CMAESLIBDEPM) MATHMORELIBDEP = $(MATHMORELIBDEPM) FUMILILIBDEP = $(FUMILILIBDEPM) TREELIBDEP = $(TREELIBDEPM) @@ -277,6 +279,7 @@ MINUITLIBEXTRA = lib/libGraf.lib lib/libHist.lib lib/libMatrix.lib \ lib/libMathCore.lib MINUIT2LIBEXTRA = lib/libGraf.lib lib/libHist.lib lib/libMatrix.lib \ lib/libMathCore.lib +CMAESLIBEXTRA = lib/libGraf.lib lib/libHist.lib lib/libMathCore.lib MATHMORELIBEXTRA = lib/libMathCore.lib FUMILILIBEXTRA = lib/libGraf.lib lib/libHist.lib lib/libMathCore.lib TREELIBEXTRA = lib/libNet.lib lib/libRIO.lib lib/libThread.lib @@ -447,6 +450,7 @@ SPECTRUMPAINTERLIBEXTRA = -Llib -lGraf -lHist HTMLLIBEXTRA = -Llib -lGraf -lThread MINUITLIBEXTRA = -Llib -lGraf -lHist -lMatrix -lMathCore MINUIT2LIBEXTRA = -Llib -lGraf -lHist -lMatrix -lMathCore +CMAESLIBEXTRA = -Llib -lGraf -lHist -lMathCore FUMILILIBEXTRA = -Llib -lGraf -lHist -lMathCore MATHMORELIBEXTRA = -Llib -lMathCore TREELIBEXTRA = -Llib -lNet -lRIO -lThread diff --git a/config/Makefile.in b/config/Makefile.in index c5d81261ab500..076ee6c14a092 100644 --- a/config/Makefile.in +++ b/config/Makefile.in @@ -395,6 +395,11 @@ BUILDROOFIT := @buildroofit@ BUILDMINUIT2 := @buildminuit2@ +BUILDCMAES := @buildcmaes@ +CMAESINCDIR := $(filter-out -I/usr/include, @cmaesincdir@) +CMAESLIBDIR := @cmaeslibdir@ +CMAESLIB := -lcmaes + BUILDUNURAN := @buildunuran@ BUILDVC := @buildvc@ diff --git a/configure b/configure index caf551e4a92fd..144af0748342d 100755 --- a/configure +++ b/configure @@ -84,6 +84,7 @@ options=" \ enable_mathmore \ enable_memstat \ enable_minuit2 \ + enable_cmaes \ enable_monalisa \ enable_mysql \ enable_odbc \ @@ -166,6 +167,7 @@ enable_qt=no enable_qtgsi=no enable_roofit=no enable_minuit2=no +enable_cmaes=yes enable_rpath=no enable_ruby=no enable_shadowpw= @@ -193,6 +195,7 @@ if test "x$ENABLEALL" = "xyes"; then enable_qtgsi=yes enable_roofit=yes enable_minuit2=yes + enable_cmaes=yes #enable_ruby=yes #not supported in ROOT v6.0.0 yet enable_table=yes enable_unuran=yes @@ -247,6 +250,7 @@ SSL \ AFS \ ROOFIT \ MINUIT2 \ +CMAES \ TABLE \ XMLDIR \ CASROOT \ @@ -1660,6 +1664,7 @@ enable/disable options, prefix with either --enable- or --disable- mathmore Build the new libMathMore extended math library, requires GSL (vers. >= 1.10) memstat A memory statistics utility, helps to detect memory leaks minuit2 Build the new libMinuit2 minimizer library + cmaes Build the wrapper to the libcmaes mininmizer library monalisa Monalisa monitoring support, requires libapmoncpp mysql MySQL support, requires libmysqlclient odbc ODBC support, requires libiodbc or libodbc @@ -2167,6 +2172,8 @@ if test $# -gt 0 ; then --with-rfio-libdir=*) shiftlibdir=$optarg ; enable_rfio="yes" ;; --with-sqlite-incdir=*) sqliteincdir=$optarg ; enable_sqlite="yes" ;; --with-sqlite-libdir=*) sqlitelibdir=$optarg ; enable_sqlite="yes" ;; + --with-cmaes-incdir=*) cmaesincdir=$optarg ; enable_cmaes="yes" ;; + --with-cmaes-libdir=*) cmaeslibdir=$optarg ; enable_cmaes="yes" ;; --with-srp=*) srpdir=$optarg ; enable_srp="yes" ;; --with-srp-incdir=*) srpincdir=$optarg ; enable_srp="yes" ;; --with-srp-libdir=*) srplibdir=$optarg ; enable_srp="yes" ;; @@ -6646,6 +6653,19 @@ else result "no" fi +###################################################################### +# +### echo %%% libcmaes support - Third party libraries +# +#check_header "cmaes.h" $HOME/include/libcmaes /usr/include/libcmaes +check_header "cmaes.h" "$cmaesincdir" /usr/include/libcmaes +cmaesinc=$found_hdr +cmaesincdir=$found_dir +check_library "libcmaes" "yes" "$cmaeslibdir" /usr/lib +# $HOME/lib /usr/lib +cmaeslib=$found_lib +cmaeslibdir=$found_dir + ###################################################################### # ### echo %%% Unuran Library - Contributed library @@ -6852,6 +6872,7 @@ if test "x$show_pkglist" = "xyes" ; then test "x$enable_fitsio" = "xyes" && pl="$pl root-plugin-graf2d-fitsio" test "x$enable_gviz" = "xyes" && pl="$pl root-plugin-graf2d-gviz" test "x$enable_minuit2" = "xyes" && pl="$pl root-plugin-math-minuit2" + test "x$enable_cmaes" = "xyes" && pl="$pl root-plugin-math-cmaes" test "x$enable_pythia6" = "xyes" && pl="$pl root-plugin-montecarlo-pythia6" test "x$enable_alien" = "xyes" && pl="$pl root-plugin-net-alien" test "x$enable_bonjour" = "xyes" && pl="$pl root-plugin-net-bonjour" @@ -6884,6 +6905,7 @@ if test "x$show_pkglist" = "xyes" ; then libroot-math-mathcore \ libroot-math-matrix \ libroot-math-minuit \ + libroot-math-cmaes \ libroot-math-mlp \ libroot-math-physics \ libroot-math-quadp \ @@ -7354,6 +7376,10 @@ sed -e "s|@aclocaldir@|$aclocaldir|" \ -e "s|@lzmalibdir@|$lzmalibdir|" \ -e "s|@buildroofit@|$enable_roofit|" \ -e "s|@buildminuit2@|$enable_minuit2|" \ + -e "s|@buildcmaes@|$enable_cmaes|" \ + -e "s|@cmaeslibdir@|$cmaeslibdir|" \ + -e "s|@cmaeslib@|$cmaeslib|" \ + -e "s|@cmaesincdir@|$cmaesincdir|" \ -e "s|@buildunuran@|$enable_unuran|" \ -e "s|@buildvc@|$enable_vc|" \ -e "s|@buildvdt@|$enable_vdt|" \ diff --git a/core/base/src/TPluginManager.cxx b/core/base/src/TPluginManager.cxx index 1738177f27368..1004d25615239 100644 --- a/core/base/src/TPluginManager.cxx +++ b/core/base/src/TPluginManager.cxx @@ -101,6 +101,7 @@ #include "TObjString.h" #include "ThreadLocalStorage.h" +#include TPluginManager *gPluginMgr; // main plugin manager created in TROOT @@ -356,7 +357,8 @@ void TPluginManager::LoadHandlersFromEnv(TEnv *env) TString ctor = strtok(0, ";\""); if (!ctor.Contains("(")) ctor = strtok(0, ";\""); - AddHandler(s, regexp, clss, plugin, ctor, "TEnv"); + std::cout << "class: " << clss << std::endl; + AddHandler(s, regexp, clss, plugin, ctor, "TEnv"); cnt++; } delete [] v; @@ -558,8 +560,8 @@ TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri) while ((h = (TPluginHandler*) next())) { if (h->CanHandle(base, uri)) { - if (gDebug > 0) - Info("FindHandler", "found plugin for %s", h->GetClass()); + /*if (gDebug > 0) + Info("FindHandler", "found plugin for %s", h->GetClass());*/ return h; } } diff --git a/etc/plugins/ROOT@@Math@@Minimizer/P010_Minuit2Minimizer.C b/etc/plugins/ROOT@@Math@@Minimizer/P010_Minuit2Minimizer.C index 781b5f7e4c03f..2575db17ce019 100644 --- a/etc/plugins/ROOT@@Math@@Minimizer/P010_Minuit2Minimizer.C +++ b/etc/plugins/ROOT@@Math@@Minimizer/P010_Minuit2Minimizer.C @@ -1,5 +1,5 @@ void P010_Minuit2Minimizer() { - gPluginMgr->AddHandler("ROOT::Math::Minimizer", "Minuit2", "ROOT::Minuit2::Minuit2Minimizer", - "Minuit2", "Minuit2Minimizer(const char *)"); + gPluginMgr->AddHandler("ROOT::Math::Minimizer", "Minuit2", "ROOT::Minuit2::Minuit2Minimizer", + "Minuit2", "Minuit2Minimizer(const char *)"); } diff --git a/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C b/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C new file mode 100644 index 0000000000000..161ffdc5a3b8e --- /dev/null +++ b/etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C @@ -0,0 +1,5 @@ +void P090_TCMAESMinimizer() +{ + gPluginMgr->AddHandler("ROOT::Math::Minimizer", "cmaes", "ROOT::cmaes::TCMAESMinimizer", + "cmaes_root", "TCMAESMinimizer(const char *)"); +} diff --git a/graf2d/asimage/src/libAfterImage/asfont.c b/graf2d/asimage/src/libAfterImage/asfont.c index 415bf6147686b..c069ddae2ab33 100644 --- a/graf2d/asimage/src/libAfterImage/asfont.c +++ b/graf2d/asimage/src/libAfterImage/asfont.c @@ -63,11 +63,11 @@ # include # include FT_FREETYPE_H # endif -# ifdef HAVE_FREETYPE_FREETYPE +/*# ifdef HAVE_FREETYPE_FREETYPE # include -# else +# else*/ # include -# endif +//# endif # if (FREETYPE_MAJOR == 2) && ((FREETYPE_MINOR == 0) || ((FREETYPE_MINOR == 1) && (FREETYPE_PATCH < 3))) # define FT_KERNING_DEFAULT ft_kerning_default # endif diff --git a/hist/hist/src/TF1.cxx b/hist/hist/src/TF1.cxx index d4acc617f5c79..04cb17afc1e6e 100644 --- a/hist/hist/src/TF1.cxx +++ b/hist/hist/src/TF1.cxx @@ -1564,7 +1564,7 @@ Double_t TF1::GetMinMaxNDim(Double_t * x , bool findmax, Double_t epsilon, Int_t stepSize = (rmax[i] - rmin[i])/100; else if (std::abs(x[i]) > 1.) stepSize = 0.1*x[i]; - + // set variable names if (ndim <= 3) { if (i == 0) { diff --git a/math/CMakeLists.txt b/math/CMakeLists.txt index c7d98b48be212..0f5ffab1825e5 100644 --- a/math/CMakeLists.txt +++ b/math/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(minuit) if(minuit2) add_subdirectory(minuit2) endif() +add_subdirectory(cmaes) add_subdirectory(fumili) add_subdirectory(physics) add_subdirectory(mlp) diff --git a/math/cmaes/CMakeLists.txt b/math/cmaes/CMakeLists.txt new file mode 100644 index 0000000000000..50316c11729c1 --- /dev/null +++ b/math/cmaes/CMakeLists.txt @@ -0,0 +1,16 @@ +############################################################################ +# CMakeLists.txt file for building ROOT math/cmaes package +############################################################################ + +ROOT_USE_PACKAGE(math/mathcore) +ROOT_USE_PACKAGE(hist/hist) + +add_definitions(-DWARNINGMSG -DUSE_ROOT_ERROR) + +include_directories(${LIBCMAES_INCLUDE_DIR}) +link_directories(${LIBCMAES_LIBRARIES}) + +ROOT_GENERATE_DICTIONARY(G__cmaes *.h MODULE cmaes LINKDEF LinkDef.h) + +ROOT_LINKER_LIBRARY(cmaes_root *.cxx G__cmaes.cxx DEPENDENCIES MathCore Hist LIBRARIES cmaes) +ROOT_INSTALL_HEADERS() \ No newline at end of file diff --git a/math/cmaes/Module.mk b/math/cmaes/Module.mk new file mode 100644 index 0000000000000..e5c19d24a402d --- /dev/null +++ b/math/cmaes/Module.mk @@ -0,0 +1,140 @@ +# Module.mk for cmaes module. + +MODNAME := cmaes +MODDIR := $(ROOT_SRCDIR)/math/$(MODNAME) +MODDIRS := $(MODDIR)/src +MODDIRI := $(MODDIR)/inc + +CMAESDIR := $(MODDIR) +CMAESDIRS := $(CMAESDIR)/src +CMAESDIRI := $(CMAESDIR)/inc +#CMAESDIRT :=$(call stripsrc,$(CMAESDIR)/test) + +CMAESBASEVERS := cmaes-1_0_0 +CMAESBASESRCS := $(MODDIRS)/$(CMAESBASEVERS).tar.gz +CMAESBASEDIRS := $(MODDIRS)/$(CMAESBASEVERS) +CMAESBASEDIRI := -I$(MODDIRS)/$(CMAESBASEVERS) +CMAESBASEETAG := $(MODDIRS)/headers.d + +##### liblcg_cmaes ##### +ifeq ($(PLATFORM),win32) +CMAESBASELIBA := $(CMAESBASEDIRS)/libcmaesbase.lib +CMAESBASELIB := $(LPATH)/libcmaesbase.lib +ifeq (debug,$(findstring debug,$(ROOTBUILD))) +CMAESBASEBLD = "DEBUG=1" +else +CMAESBASEBLD = "" +endif +else +CMAESBASELIBA := $(CMAESBASEDIRS)/src/.libs/liblcg_cmaes.a +CMAESBASELIB := $(LPATH)/libcmaesbase.a +endif +CMAESBASEDEP := $(CMAESBASELIB) + +##### libcmaes ##### +CMAESL := $(MODDIRI)/LinkDef.h +CMAESDS := $(call stripsrc,$(MODDIRS)/G__cmaes.cxx) +CMAESDO := $(CMAESDS:.cxx=.o) +CMAESDH := $(CMAESDS:.cxx=.h) + +CMAESAH := $(filter-out $(MODDIRI)/LinkDef%,$(wildcard $(MODDIRI)/*.h)) +CMAESBH := $(filter-out $(MODDIRI)/cmaes/LinkDef%,$(wildcard $(MODDIRI)/cmaes/*.h)) +CMAESH := $(CMAESAH) $(CMAESBH) +CMAESS := $(filter-out $(MODDIRS)/G__%,$(wildcard $(MODDIRS)/*.cxx)) +CMAESO := $(call stripsrc,$(CMAESS:.cxx=.o)) + +CMAESDEP := $(CMAESO:.o=.d) $(CMAESDO:.o=.d) + +CMAESLIB := $(LPATH)/libcmaes_root.$(SOEXT) +CMAESMAP := $(CMAESLIB:.$(SOEXT)=.rootmap) + +# use this compiler option if want to optimize object allocation in cmaes +# NOTE: using this option one loses the thread safety. +# It is worth to use only for minimization of cheap (non CPU intensive) functions +#CXXFLAGS += -DMN_USE_STACK_ALLOC + +# used in the main Makefile +ALLHDRS += $(patsubst $(MODDIRI)/%.h,include/%.h,$(CMAESH)) +ALLLIBS += $(CMAESLIB) +ALLMAPS += $(CMAESMAP) + +# include all dependency files +INCLUDEFILES += $(CMAESDEP) + +##### local rules ##### +.PHONY: all-$(MODNAME) clean-$(MODNAME) distclean-$(MODNAME) \ + test-$(MODNAME) + +include/cmaes/%.h: $(CMAESDIRI)/cmaes/%.h + @(if [ ! -d "include/cmaes" ]; then \ + mkdir -p include/cmaes; \ + fi) + cp $< $@ + +include/%.h: $(CMAESDIRI)/%.h + cp $< $@ + +$(CMAESLIB): $(CMAESO) $(CMAESDO) $(ORDER_) $(MAINLIBS) $(CMAESLIBDEP) + @$(MAKELIB) $(PLATFORM) $(LD) "$(LDFLAGS)" \ + "$(SOFLAGS)" libcmaes_root.$(SOEXT) $@ \ + "$(CMAESO) $(CMAESDO)" "-lcmaes -lMathCore" "$(CMAESLIBEXTRA)" + +$(call pcmrule,CMAES) + $(noop) + +$(CMAESDS): $(CMAESH) $(CMAESL) $(ROOTCLINGEXE) $(call pcmdep,CMAES) + $(MAKEDIR) + @echo "Generating dictionary $@..." + $(ROOTCLINGSTAGE2) -f $@ $(call dictModule,CMAES) -I$(CMAESINCDIR) -I/usr/include/eigen3 -c $(CMAESH) $(CMAESL) + +$(CMAESMAP): $(CMAESH) $(CMAESL) $(ROOTCLINGEXE) $(call pcmdep,CMAES) + $(MAKEDIR) + @echo "Generating rootmap $@..." + $(ROOTCLINGSTAGE2) -r $(CMAESDS) $(call dictModule,CMAES) -c $(CMAESH) $(CMAESL) + +all-$(MODNAME): $(CMAESLIB) + +#test-$(MODNAME): all-$(MODNAME) +#ifneq ($(ROOT_OBJDIR),$(ROOT_SRCDIR)) +# @$(INSTALL) $(CMAESDIR)/test $(CMAESDIRT) +#endif + @cd $(CMAESDIRT) && $(MAKE) ROOTCONFIG=../../../bin/root-config + +clean-$(MODNAME): + @rm -f $(CMAESO) $(CMAESDO) + +clean:: clean-$(MODNAME) + +distclean-$(MODNAME): clean-$(MODNAME) + @rm -f $(CMAESDEP) $(CMAESDS) $(CMAESDH) $(CMAESLIB) \ + $(CMAESMAP) + @rm -rf include/cmaes +ifneq ($(ROOT_OBJDIR),$(ROOT_SRCDIR)) + @rm -rf $(CMAESDIRT) +else + @cd $(CMAESDIRT) && $(MAKE) distclean ROOTCONFIG=../../../bin/root-config +endif + +distclean:: distclean-$(MODNAME) + +##### extra rules ###### +$(CMAESO): CXXFLAGS += -DWARNINGMSG -DUSE_ROOT_ERROR +$(CMAESDO): CXXFLAGS += -DWARNINGMSG -DUSE_ROOT_ERROR +#for thread -safet +#$(CMAESO): CXXFLAGS += -DCMAES_THREAD_SAFE +# for openMP +#ifneq ($(USE_PARALLEL_CMAES),) +#ifneq ($(USE_OPENMP),) +#$(CMAESO): CXXFLAGS += -DCMAES_THREAD_SAFE -DCMAES_PARALLEL_OPENMP +#math/cmaes/src/Numerical2PGradientCalculator.o: +$(CMAESO):CXXFLAGS += -D_GLIBCXX_PARALLEL -fopenmp +$(CMAESDO):CXXFLAGS += -D_GLIBCXX_PARALLEL -fopenmp +$(CMAESLIB):LDFLAGS += -fopenmp +#endif + +$(CMAESO):CXXFLAGS += -I$(CMAESINCDIR) -I/usr/include/eigen3 +$(CMAESDO):CXXFLAGS += -I$(CMAESINCDIR) -I/usr/include/eigen3 +$(CMAESDS):CXXFLAGS += -I$(CMAESINCDIR) -I/usr/include/eigen3 +$(CMAESLIB):LDFLAGS += $(CMAESLIBDIR) +# Optimize dictionary with stl containers. +$(CMAESDO): NOOPT = $(OPT) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h new file mode 100644 index 0000000000000..98b96d2ee22d5 --- /dev/null +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -0,0 +1,313 @@ +/** + * CMA-ES, Covariance Matrix Evolution Strategy + * Copyright (c) 2014 INRIA + * Author: Emmanuel Benazera + * + * This file is part of libcmaes. + * + * libcmaes is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libcmaes is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libcmaes. If not, see . + */ + +#ifndef ROOT_CMAES_CMAESMinimizer +#define ROOT_CMAES_CMAESMinimizer + +#ifndef ROOT_Math_Minimizer +#include "Math/Minimizer.h" +#endif + +#ifndef ROOT_Math_IFunctionfwd +#include "Math/IFunctionfwd.h" +#endif + +#include "cmaes.h" + +using namespace libcmaes; + +namespace ROOT +{ + namespace cmaes + { + + class TCMAESMinimizer : public ROOT::Math::Minimizer + { + public: + + /** + * Default constructor + */ + TCMAESMinimizer(); // CMAES_DEFAULT + + /** + * Constructor with a char (used by PM) + */ + TCMAESMinimizer(const char *type); + + /** + * Destructor + */ + virtual ~TCMAESMinimizer(); + + private: + // blocking copy constructor. + TCMAESMinimizer(const TCMAESMinimizer &m); + + /** + * assignment operator. + */ + TCMAESMinimizer& operator = (const TCMAESMinimizer &rhs); + + public: + + // clear resources (parameters) for consecutives minimizations + virtual void Clear(); + + /// set the function to minimize + virtual void SetFunction(const ROOT::Math::IMultiGenFunction & func); + + /// set gradient the function to minimize + virtual void SetFunction(const ROOT::Math::IMultiGradFunction & func); + + /// set free variable + virtual bool SetVariable(unsigned int ivar, const std::string & name, double val, double step); + + /// set lower limit variable (override if minimizer supports them ) + virtual bool SetLowerLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double lower ); + /// set upper limit variable (override if minimizer supports them ) + virtual bool SetUpperLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double upper ); + /// set upper/lower limited variable (override if minimizer supports them ) + virtual bool SetLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double /* lower */, double /* upper */); + /// set fixed variable (override if minimizer supports them ) + virtual bool SetFixedVariable(unsigned int /* ivar */, const std::string & /* name */, double /* val */); + /// set variable + virtual bool SetVariableValue(unsigned int ivar, double val); + // set variable values + virtual bool SetVariableValues(const double * val); + /// set the step size of an already existing variable + virtual bool SetVariableStepSize(unsigned int ivar, double step ); + /// set the lower-limit of an already existing variable + virtual bool SetVariableLowerLimit(unsigned int ivar, double lower); + /// set the upper-limit of an already existing variable + virtual bool SetVariableUpperLimit(unsigned int ivar, double upper); + /// set the limits of an already existing variable + virtual bool SetVariableLimits(unsigned int ivar, double lower, double upper); + /// fix an existing variable + virtual bool FixVariable(unsigned int ivar); + /// release an existing variable + //virtual bool ReleaseVariable(unsigned int ivar); + /// query if an existing variable is fixed (i.e. considered constant in the minimization) + /// note that by default all variables are not fixed + virtual bool IsFixedVariable(unsigned int ivar) const; + /// get variable settings in a variable object (like ROOT::Fit::ParamsSettings) + virtual bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings & varObj) const; + /// get name of variables (override if minimizer support storing of variable names) + virtual std::string VariableName(unsigned int ivar) const; + /// get index of variable given a variable given a name + /// return -1 if variable is not found + virtual int VariableIndex(const std::string & name) const; + + // sets libcmaes parameter object based on options. + template + void SetMParameters(CMAParameters &cmaparams, + const int &maxiter, const int &maxfevals, + const int &noisy, const int &nrestarts, + const double &ftarget, + const std::string &fplot, + const bool &withnumgradient, + const bool &mtfeval, + const bool &quiet); + + /** + method to perform the minimization. + Return false in case the minimization did not converge. In this case a + status code different than zero is set + (retrieved by the derived method Minimizer::Status() )" + + status = 1 : Covariance was made pos defined -> not yet implemented in libcmaes + status = 2 : Hesse is invalid => Not Applicable, kept for correspondence with Minuit2 + status = 3 : Edm is above max + status = 4 : Reached call limit + status = 5 : Any other failure + */ + virtual bool Minimize(); + + /// return minimum function value + virtual double MinValue() const; + + /// return expected distance reached from the minimum + virtual double Edm() const; + + /// return pointer to X values at the minimum + virtual const double * X() const; + + /// return pointer to gradient values at the minimum + virtual const double * MinGradient() const { return 0; } // not available in CMAES + + /// number of function calls to reach the minimum + virtual unsigned int NCalls() const; + + /// this is <= Function().NDim() which is the total + /// number of variables (free+ constrained ones) + virtual unsigned int NDim() const { return fDim; } + + /// number of free variables (real dimension of the problem) + /// this is <= Function().NDim() which is the total + virtual unsigned int NFree() const { return fFreeDim; } + + /// minimizer provides error and error matrix + virtual bool ProvidesError() const { return true; } + + /// return errors at the minimum + virtual const double* Errors() const; + + /** + return covariance matrix elements + if the variable is fixed or const the value is zero + The ordering of the variables is the same as in errors and parameter value. + This is different from the direct interface of Minuit2 or TMinuit where the + values were obtained only to variable parameters + */ + virtual double CovMatrix(unsigned int i, unsigned int j) const; + + + /** + Fill the passed array with the covariance matrix elements + if the variable is fixed or const the value is zero. + The array will be filled as cov[i *ndim + j] + The ordering of the variables is the same as in errors and parameter value. + This is different from the direct interface of Minuit2 or TMinuit where the + values were obtained only to variable parameters + */ + virtual bool GetCovMatrix(double * cov) const; + + /** + Fill the passed array with the Hessian matrix elements + The Hessian matrix is the matrix of the second derivatives + and is the inverse of the covariance matrix + If the variable is fixed or const the values for that variables are zero. + The array will be filled as h[i *ndim + j] + */ + //virtual bool GetHessianMatrix(double * h) const; + + + /** + return the status of the covariance matrix + status = -1 : not available (inversion failed or Hesse failed) + status = 0 : available but not positive defined + status = 1 : covariance only approximate + status = 2 : full matrix but forced pos def + status = 3 : full accurate matrix + + */ + virtual int CovMatrixStatus() const { return 3; } + /** + return correlation coefficient between variable i and j. + If the variable is fixed or const the return value is zero + */ + virtual double Correlation(unsigned int i, unsigned int j ) const; + + /** + get global correlation coefficient for the variable i. This is a number between zero and one which gives + the correlation between the i-th variable and that linear combination of all other variables which + is most strongly correlated with i. + If the variable is fixed or const the return value is zero + */ + virtual double GlobalCC(unsigned int i) const; + + /** + get the minos error for parameter i, return false if Minos failed + A minimizaiton must be performed befre, return false if no minimization has been done + In case of Minos failed the status error is updated as following + status += 10 * minosStatus where the minos status is: + status = 1 : maximum number of function calls exceeded when running for lower error + status = 2 : maximum number of function calls exceeded when running for upper error + status = 3 : new minimum found when running for lower error + status = 4 : new minimum found when running for upper error + status = 5 : any other failure + + */ + virtual bool GetMinosError(unsigned int i, double & errLow, double & errUp, int = 0); + + /** + scan a parameter i around the minimum. A minimization must have been done before, + return false if it is not the case + */ + //TODO + virtual bool Scan(unsigned int i, unsigned int & nstep, double * x, double * y, double xmin = 0, double xmax = 0); + + /** + find the contour points (xi,xj) of the function for parameter i and j around the minimum + The contour will be find for value of the function = Min + ErrorUp(); + */ + //TODO + virtual bool Contour(unsigned int i, unsigned int j, unsigned int & npoints, double *xi, double *xj); + + + /** + perform a full calculation of the Hessian matrix for error calculation + If a valid minimum exists the calculation is done on the minimum point otherwise is performed + in the current set values of parameters + Status code of minimizer is updated according to the following convention (in case Hesse failed) + status += 100*hesseStatus where hesse status is: + status = 1 : hesse failed + status = 2 : matrix inversion failed + status = 3 : matrix is not pos defined + */ + //virtual bool Hesse(); + + + /// return reference to the objective function + //virtual const ROOT::Math::IGenFunction & Function() const; + + /// print result of minimization + virtual void PrintResults(); + + /// set an object to trace operation for each iteration + /// The object muust implement operator() (unsigned int, MinimumState & state) + //void SetTraceObject(MnTraceObject & obj); + + /// set storage level = 1 : store all iteration states (default) + /// = 0 : store only first and last state to save memory + //TODO. + void SetStorageLevel(int level); + + private: + unsigned int fDim = 0; // dimension of the function to be minimized + unsigned int fFreeDim = 0; // Number of free dimensions. + int fMinimizer = CMAES_DEFAULT; // minimizer algo. + const ROOT::Math::IMultiGenFunction *fObjFunc = nullptr; + const ROOT::Math::IMultiGradFunction *fObjFuncGrad = nullptr; + std::vector fLBounds; // Lower bounds of variables + std::vector fUBounds; // Upper bounds of variables + std::vector fVariablesType; // 0 for free variable, 1 for fixed variable, 2 for lower bounded, 3 for upper bounded, 4 for lower and upper bounded. + std::vector fInitialX; + std::vector fNames; // Names of the variables. + std::vector fInitialSigma; // User-set Initial step-size for each variables. + std::map fFixedVariables; // fixed variables and values. + CMASolutions fCMAsols; + CMAParameters> fCMAparams; // params no bounds. + CMAParameters> fCMAparams_b; // params with bounds. + CMAParameters> fCMAparams_l; // params no bounds + linear scaling. + CMAParameters> fCMAparams_lb; // params with bounds + linear scaling. + mutable std::vector fGlobalCC; // vector of global correlation coefficients. + mutable std::vector fValues; // X values. + mutable std::vector fErrors; // X errors. + bool fWithBounds = false; // whether using box-type constraints as required by parameters. + bool fWithGradient = false; // whether to use gradient information when available. + int fWithLinearScaling = 0; // wheter to use linear scaling of objective function parameters. */ + }; + + } // end namespace cmaes +} // end namespace ROOT + +#endif diff --git a/math/cmaes/inc/LinkDef.h b/math/cmaes/inc/LinkDef.h new file mode 100644 index 0000000000000..c5a1c5e2825ba --- /dev/null +++ b/math/cmaes/inc/LinkDef.h @@ -0,0 +1,30 @@ +/** + * CMA-ES, Covariance Matrix Evolution Strategy + * Copyright (c) 2014 INRIA + * Author: Emmanuel Benazera + * + * This file is part of libcmaes. + * + * libcmaes is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libcmaes is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libcmaes. If not, see . + */ + +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class TCMAESMinimizer; + +#endif diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx new file mode 100644 index 0000000000000..75f563a971aa4 --- /dev/null +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -0,0 +1,705 @@ +/** + * CMA-ES, Covariance Matrix Evolution Strategy + * Copyright (c) 2014 INRIA + * Author: Emmanuel Benazera + * + * This file is part of libcmaes. + * + * libcmaes is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libcmaes is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libcmaes. If not, see . + */ + +#include "CMAESMinimizer.h" +#include "Math/IFunctionfwd.h" // fObjFunc +#include "Math/IOptions.h" +#include "Math/Error.h" +#include "Fit/ParameterSettings.h" + +#include "errstats.h" // libcmaes extras. + +#ifdef USE_ROOT_ERROR +#include "TROOT.h" +#endif + +#include + +using namespace libcmaes; + +namespace ROOT +{ + // registers a default empty set of extra options. + //ROOT::Math::IOptions &defIOptions = ROOT::Math::MinimizerOptions::Default("cmaes"); + + namespace cmaes + { + + TCMAESMinimizer::TCMAESMinimizer() + :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false),fWithGradient(false) + { + } + + TCMAESMinimizer::TCMAESMinimizer(const char *type) + :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false),fWithGradient(false) + { + std::string algoname(type); + // tolower() is not an std function (Windows) + std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int(*)(int)) tolower ); + if (algoname == "cmaes") + fMinimizer = CMAES_DEFAULT; + else if (algoname == "ipop") + fMinimizer = IPOP_CMAES; + else if (algoname == "bipop") + fMinimizer = BIPOP_CMAES; + else if (algoname == "acmaes") + fMinimizer = aCMAES; + else if (algoname == "aipop") + fMinimizer = aIPOP_CMAES; + else if (algoname == "abipop") + fMinimizer = aBIPOP_CMAES; + else if (algoname == "sepcmaes") + fMinimizer = sepCMAES; + else if (algoname == "sepipop") + fMinimizer = sepIPOP_CMAES; + else if (algoname == "sepbipop") + fMinimizer = sepBIPOP_CMAES; + } + + TCMAESMinimizer::TCMAESMinimizer(const TCMAESMinimizer &m) + :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false),fWithGradient(false) + { + } + + TCMAESMinimizer& TCMAESMinimizer::operator = (const TCMAESMinimizer &rhs) + { + if (this == &rhs) return *this; + return *this; + } + + TCMAESMinimizer::~TCMAESMinimizer() + { + } + + void TCMAESMinimizer::Clear() + { + std::cout << "clearing up minimizer\n"; + fCMAsols = CMASolutions(); + fCMAparams = CMAParameters>(); + fCMAparams_b = CMAParameters>(); + fCMAparams_l = CMAParameters>(); + fCMAparams_lb = CMAParameters>(); + fDim = 0; fFreeDim = 0; + fLBounds.clear(); + fUBounds.clear(); + fVariablesType.clear(); + fInitialX.clear(); + fInitialSigma.clear(); + fFixedVariables.clear(); + fNames.clear(); + fGlobalCC.clear(); + fValues.clear(); + fErrors.clear(); + } + + void TCMAESMinimizer::SetFunction(const ROOT::Math::IMultiGenFunction &fun) + { + fObjFunc = &fun; + fDim = fun.NDim(); + } + + void TCMAESMinimizer::SetFunction(const ROOT::Math::IMultiGradFunction &fun) + { + SetFunction(static_cast (fun)); + fObjFuncGrad = &fun; + //fDim = fun.NDim(); + fWithGradient = true; + } + + bool TCMAESMinimizer::SetVariable(unsigned int ivar, const std::string & name, double val, double step) + { + if (ivar > fInitialX.size() ) { + MATH_ERROR_MSG("TCMAESMinimizer::SetVariable","ivar out of range"); + return false; + } + if (ivar == fInitialX.size() ) { + fInitialX.push_back(val); + fNames.push_back(name); + fInitialSigma.push_back(step); + fLBounds.push_back(-std::numeric_limits::max()); + fUBounds.push_back(std::numeric_limits::max()); + if (step==0.){ + fVariablesType.push_back(1); + } + else { + fFreeDim++; + fVariablesType.push_back(0); + } + } + else { + if (step==0.) { + if (fInitialSigma[ivar]!=0.) { //Constraining a free variable. + fFreeDim--; + fVariablesType[ivar] = 1; + } + } + else { + if (fInitialSigma[ivar]==0.) { //Freeing a constrained variable + fFreeDim++; + fVariablesType[ivar] = 0; + } + } + fInitialX[ivar] = val; + fNames[ivar] = name; + fInitialSigma[ivar] = step; + } + return true; + } + + bool TCMAESMinimizer::SetLowerLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double lower ) + { + if (lower > val) { + MATH_WARN_MSG("TCMAESMinimizer::SetLowerLimitedVariable", "Starting point set into the unfeasible domain"); // fix with val=lower; ? + } + bool r = SetVariable(ivar, name, val, step); + if (!r) return false; + fLBounds[ivar] = lower; + fVariablesType[ivar] = 2; + fWithBounds = true; + return true; + } + + bool TCMAESMinimizer::SetUpperLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double upper ) + { + if (upper > val) { + MATH_WARN_MSG("TCMAESMinimizer::SetUpperLimitedVariable", "Starting point set into the unfeasible domain"); + } + bool r = SetVariable(ivar, name, val, step); + if (!r) return false; + fUBounds[ivar] = upper; + fVariablesType[ivar] = 3; + fWithBounds = true; + return true; + } + + bool TCMAESMinimizer::SetLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double lower, double upper) + { + if (upper == lower) { + MATH_WARN_MSG("TCMAESMinimizer::SetLimitedVariable","Upper bound equal to lower bound. Variable is constrained to fixed value."); + return SetFixedVariable(ivar, name, val); + } + if (upper < lower) { + MATH_WARN_MSG("TCMAESMinimizer::SetLimitedVariable","Upper bound lesser than lower bound. Bounds exchanged."); + double temp(upper); + upper = lower; + lower = temp; + } + if (val < lower || val > upper) { + MATH_WARN_MSG("TCMAESMinimizer::SetLimitedVariable", "Starting point set into the unfeasible domain"); + } + bool r = SetVariable(ivar, name, val, step); + if (!r) return false; + fLBounds[ivar] = lower; + fUBounds[ivar] = upper; + fVariablesType[ivar] = 4; + fWithBounds = true; + return true; + } + + bool TCMAESMinimizer::SetFixedVariable(unsigned int ivar, const std::string &name, double val) + { + SetVariable(ivar,name,val,0.0); + fFixedVariables.insert(std::pair(ivar,val)); + } + + bool TCMAESMinimizer::SetVariableValue(unsigned int ivar, double val ) + { + if (ivar >= fInitialX.size() ) { + //TODO string that gives value of ivar and fInitialX.size() + MATH_ERROR_MSG("TCMAESMinimizer::SetVariableValue","ivar out of range"); + return false; + } + if (fVariablesType[ivar] == 2 || fVariablesType[ivar] == 4) { + if (fLBounds[ivar] > val) { + MATH_WARN_MSG("TCMAESMinimizer::SetVariableValue", "Starting point set into the unfeasible domain"); + } + } + if (fVariablesType[ivar] == 3 || fVariablesType[ivar] == 4) { + if (fUBounds[ivar] < val) { + MATH_WARN_MSG("TCMAESMinimizer::SetVariableValue", "Starting point set into the unfeasible domain"); + } + } + fInitialX[ivar] = val; + return true; + } + + bool TCMAESMinimizer::SetVariableValues(const double * x) + { + if (x == NULL) + { + MATH_WARN_MSG("TCMAESMinimizer::SetVariableValues", "No values given, no change to the starting point."); + return false; + } + unsigned int i; + for (i=0; i fInitialX.size()) + return false; + fInitialSigma[ivar] = step; + return true; + } + + bool TCMAESMinimizer::SetVariableLowerLimit(unsigned int ivar, double lower) + { + if (ivar > fLBounds.size()) + return false; + fLBounds[ivar] = lower; + fVariablesType[ivar] = 2; + fWithBounds = true; + return true; + } + + bool TCMAESMinimizer::SetVariableUpperLimit(unsigned int ivar, double upper) + { + if (ivar > fUBounds.size()) + return false; + fUBounds[ivar] = upper; + fVariablesType[ivar] = 3; + fWithBounds = true; + return true; + } + + bool TCMAESMinimizer::SetVariableLimits(unsigned int ivar, double lower, double upper) + { + if (ivar >= fLBounds.size() || ivar >= fUBounds.size()) + return false; + fLBounds[ivar] = lower; + fUBounds[ivar] = upper; + fVariablesType[ivar] = 4; + fWithBounds = true; + return true; + } + + bool TCMAESMinimizer::FixVariable(unsigned int ivar) + { + fFixedVariables.insert(std::pair(ivar,fInitialX.at(ivar))); // XXX: sets initial variable. + } + + bool TCMAESMinimizer::IsFixedVariable(unsigned int ivar) const + { + std::map::const_iterator mit; + if ((mit=fFixedVariables.find(ivar))!=fFixedVariables.end()) + return true; + return false; + } + + bool TCMAESMinimizer::GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const + { + if (ivar >= fInitialX.size()) + { + MATH_ERROR_MSG("TCMAESMinimizer::GetVariableSettings","wrong variable index"); + return false; + } + varObj.Set(fNames.at(ivar),fInitialX.at(ivar),false); //XXX: not sure of last param type. + if (fVariablesType.at(ivar) == 4) + varObj.SetLimits(fLBounds.at(ivar),fUBounds.at(ivar)); + else if (fVariablesType.at(ivar) == 3) + varObj.SetUpperLimit(fUBounds.at(ivar)); + else if (fVariablesType.at(ivar) == 2) + varObj.SetLowerLimit(fLBounds.at(ivar)); + return true; + } + + std::string TCMAESMinimizer::VariableName(unsigned int ivar) const + { + if (ivar >= fInitialX.size()) + return std::string(); + return fNames.at(ivar); + } + + int TCMAESMinimizer::VariableIndex(const std::string &name) const + { + for (unsigned int i=0;i + void TCMAESMinimizer::SetMParameters(CMAParameters &cmaparams, + const int &maxiter, const int &maxfevals, + const int &noisy, const int &nrestarts, + const double &ftarget, + const std::string &fplot, + const bool &withnumgradient, + const bool &mtfeval, + const bool &quiet) + { + cmaparams.set_algo(fMinimizer); + if (gDebug > 0 || !quiet) + cmaparams.set_quiet(false); + else cmaparams.set_quiet(true); + for (auto mit=fFixedVariables.begin();mit!=fFixedVariables.end();mit++) + cmaparams.set_fixed_p((*mit).first,(*mit).second); + cmaparams.set_edm(true); // always activate EDM computation. + cmaparams.set_ftolerance(Tolerance()); + cmaparams.set_max_iter(maxiter); + cmaparams.set_max_fevals(maxfevals); + if (noisy > 0) + cmaparams.set_noisy(); + if (nrestarts > 0) + cmaparams.set_restarts(nrestarts); + if (ftarget > 0.0) + cmaparams.set_ftarget(ftarget); + cmaparams.set_fplot(fplot); + cmaparams.set_gradient(withnumgradient); + cmaparams.set_mt_feval(mtfeval); + } + + bool TCMAESMinimizer::Minimize() + { + if (!fObjFunc) { + MATH_ERROR_MSG("TCMAESMinimizer::Minimize","Objective function has not been set"); + return false; + } + if (!fDim) { + MATH_ERROR_MSG("TCMAESMinimizer::Minimize","Dimension has not been set"); + return false; + } + if (fDim > fInitialX.size()) { + std::cout << "fDim=" << fDim << " / fInitialX size=" << fInitialX.size() << " / freeDim=" << fFreeDim << std::endl; + MATH_ERROR_MSG("TCMAESMinimizer::Minimize","Dimension larger than initial X size's"); + return false; + } + if (fDim < fInitialX.size()) { + MATH_WARN_MSG("TCMAESMinimizer::Minimize","Dimension smaller than initial X size's"); + } + + ROOT::Math::IOptions *cmaesOpt = ROOT::Math::MinimizerOptions::FindDefault("cmaes"); + //std::cerr << "cmaesOpt ptr: " << cmaesOpt << std::endl; + if (cmaesOpt) + cmaesOpt->Print(std::cout); + + FitFunc ffit = [this](const double *x, const int N) + { + /*std::copy(x,x+N,std::ostream_iterator(std::cout," ")); + std::cout << std::endl;*/ + return (*fObjFunc)(x); + }; + + // gradient function. + //std::cout << "fWithGradient=" << fWithGradient << std::endl; + GradFunc gfit = nullptr; + if (fWithGradient) + { + gfit = [this](const double *x, const int N) + { + dVec grad(N); + fObjFuncGrad->Gradient(x,grad.data()); + return grad; + }; + } + + //debug + /*if (fWithBounds) + { + std::cout << "bounds:\n"; + std::copy(fLBounds.begin(),fLBounds.end(),std::ostream_iterator(std::cout," ")); + std::cout << std::endl; + std::copy(fUBounds.begin(),fUBounds.end(),std::ostream_iterator(std::cout," ")); + std::cout << std::endl; + }*/ + //debug + + double sigma0 = *std::min_element(fInitialSigma.begin(),fInitialSigma.end()); + double sigma0scaled = 1e-1; // default value. + if (!fWithLinearScaling) + sigma0scaled = sigma0; + dVec vscaling = dVec::Constant(fDim,1.0); + for (size_t i=0;iGetValue("lambda",lambda); + cmaesOpt->GetValue("noisy",noisy); + cmaesOpt->GetValue("restarts",nrestarts); + cmaesOpt->GetValue("ftarget",ftarget); + cmaesOpt->GetValue("fplot",fplot); + cmaesOpt->GetValue("lscaling",fWithLinearScaling); + cmaesOpt->GetValue("numgradient",withnumgradient); + cmaesOpt->GetValue("mt_feval",mtfeval); + cmaesOpt->GetValue("quiet",quiet); + cmaesOpt->GetValue("seed",seed); + } + + if (gDebug > 0) + { + std::cout << "Running CMA-ES with dim=" << fDim << " / sigma0=" << sigma0scaled << " / lambda=" << lambda << " / fTol=" << Tolerance() << " / with_bounds=" << fWithBounds << " / with_gradient=" << fWithGradient << " / linear_scaling=" << fWithLinearScaling << " / maxiter=" << maxiter << " / maxfevals=" << maxfevals << " / mtfeval=" << mtfeval << std::endl; + std::cout << "x0="; + std::copy(fInitialX.begin(),fInitialX.end(),std::ostream_iterator(std::cout," ")); + std::cout << std::endl; + } + + if (fWithLinearScaling) + { + if (fWithBounds) + { + Info("CMAESMinimizer","Minimizing with bounds and linear scaling"); + /*ProgressFunc>,CMASolutions> pfunc = [](const CMAParameters> &cmaparams, const CMASolutions &cmasols) + { + std::cout << "iter=" << cmasols.niter() << " / evals=" << cmasols.nevals() << " / f-value=" << cmasols.best_candidate().get_fvalue() << " / sigma=" << cmasols.sigma() << std::endl; + std::cout << "best x=" << cmaparams.get_gp().pheno(cmasols.best_candidate().get_x_dvec()).transpose() << std::endl; + return 0; + };*/ + GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); + fCMAparams_lb = cmaparams; + } + else + { + //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; + Info("CMAESMinimizer","Minimizing with linear scaling"); + GenoPheno gp(vscaling,vshift); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); + fCMAparams_l = cmaparams; + } + } + else + { + if (fWithBounds) + { + Info("CMAESMinimizer","Minimizing with bounds"); + GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); + fCMAparams_b = cmaparams; + } + else + { + Info("CMAESMinimizer","Minimizing without bounds or linear scaling"); + CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); + fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); + fCMAparams = cmaparams; + } + } + Info("CMAESMinimizer","optimization status=%i",fCMAsols.run_status()); + if (fCMAsols.edm() > 10*Tolerance()) // XXX: max edm seems to be left to each minimizer's internal implementation... + fStatus = 3; + else if (fCMAsols.run_status() == 0 || fCMAsols.run_status() == 1) + fStatus = 0; + else if (fCMAsols.run_status() == 7 || fCMAsols.run_status() == 9) + fStatus = 4; // reached budget limit. + else fStatus = 5; + return fCMAsols.run_status() >= 0; // above 0 are partial successes at worst. + } + + double TCMAESMinimizer::MinValue() const + { + return fCMAsols.best_candidate().get_fvalue(); + } + + const double* TCMAESMinimizer::X() const + { + fValues.clear(); + Candidate bc = fCMAsols.best_candidate(); + + dVec x; + if (fWithLinearScaling) + { + if (fWithBounds) + x = bc.get_x_pheno_dvec>(fCMAparams_lb); + else x = bc.get_x_pheno_dvec>(fCMAparams_l); + } + else + { + if (fWithBounds) + x = bc.get_x_pheno_dvec>(fCMAparams_b); + else x = bc.get_x_dvec(); + } + for (int i=0;i 0.0) + fGlobalCC.push_back(0.0); + else fGlobalCC.push_back(std::sqrt(1.0 - 1.0/denom)); + } + } + return fGlobalCC.at(i); + } + + bool TCMAESMinimizer::GetMinosError(unsigned int i, double &errLow, double &errUp, int j) + { + FitFunc ffit = [this](const double *x, const int N) + { + return (*fObjFunc)(x); + }; + + // runopt is a flag which specifies if only lower or upper error needs to be run. TODO: support for one bound only in libcmaes ? + int samplesize = 10; + if (gDebug > 0) + std::cerr << "Computing 'Minos' confidence interval with profile likelihood on parameter " << i << " / samplesize=" << samplesize << " / with_bounds=" << fWithBounds << std::endl; + pli le; + if (fWithLinearScaling) + { + if (!fWithBounds) + { + le = errstats>::profile_likelihood(ffit,fCMAparams_l,fCMAsols,i,false,samplesize,ErrorDef()); + } + else + { + le = errstats>::profile_likelihood(ffit,fCMAparams_lb,fCMAsols,i,false,samplesize); + } + } + else + { + if (!fWithBounds) + { + le = errstats>::profile_likelihood(ffit,fCMAparams,fCMAsols,i,false,samplesize,ErrorDef()); + } + else + { + le = errstats>::profile_likelihood(ffit,fCMAparams_b,fCMAsols,i,false,samplesize); + } + } + errLow = le.get_err_min(); + errUp = le.get_err_max(); + return true; + } + + bool TCMAESMinimizer::Scan(unsigned int i, unsigned int &nstep, double *x, double *y, double xmin, double xmax) + { + //TODO. + return false; + } + + bool TCMAESMinimizer::Contour(unsigned int i, unsigned int j, unsigned int &npoints, double *xi, double *xj) + { + //TODO. + return false; + } + + void TCMAESMinimizer::PrintResults() + { + std::cout << "CMAESMinimizer : Valid minimum - status = " << fStatus << std::endl; + std::cout << "FVAL = " << MinValue() << std::endl; + std::cout << "Nfcn = " << NCalls() << std::endl; + std::cout << "Edm = " << Edm() << std::endl; + std::map::const_iterator mit; + for (unsigned int i=0;i 1) + std::cout << "\t(limited)"; + std::cout << std::endl; + } + } + + } +} diff --git a/math/cmaes/test/CMakeLists.txt b/math/cmaes/test/CMakeLists.txt new file mode 100644 index 0000000000000..e41053d5999d0 --- /dev/null +++ b/math/cmaes/test/CMakeLists.txt @@ -0,0 +1,66 @@ +project(cmaes-tests) +find_package(ROOT REQUIRED) + +include(${ROOT_USE_FILE}) +include_directories(${ROOT_INCLUDE_DIRS}) + +set(TestSource + testMinimizer.cxx +) + +set(TestSourceMnTutorial + MnTutorial/Quad1FMain.cxx + MnTutorial/Quad4FMain.cxx + MnTutorial/Quad8FMain.cxx + MnTutorial/Quad12FMain.cxx +) + +set(TestSourceMnSim + MnSim/DemoGaussSim.cxx + MnSim/DemoFumili.cxx + MnSim/PaulTest.cxx + MnSim/PaulTest2.cxx + MnSim/PaulTest3.cxx + MnSim/PaulTest4.cxx + MnSim/ReneTest.cxx + MnSim/ParallelTest.cxx + MnSim/demoMinimizer.cxx +) + + + + +#---For the simple cmaes tests build and defined them--------------- +foreach(file ${TestSourceMnTutorial}) + get_filename_component(testname ${file} NAME_WE) + ROOT_EXECUTABLE(${testname} ${file} LIBRARIES cmaes) + ROOT_ADD_TEST(minuit2-${testname} COMMAND ${testname}) +endforeach() + + +ROOT_LINKER_LIBRARY(Minuit2TestMnSim MnSim/GaussDataGen.cxx MnSim/GaussFcn.cxx MnSim/GaussFcn2.cxx LIBRARIES Minuit2) + +#input text files +configure_file(MnSim/paul.txt paul.txt @COPY_ONLY) +configure_file(MnSim/paul2.txt paul2.txt @COPY_ONLY) +configure_file(MnSim/paul3.txt paul3.txt @COPY_ONLY) +configure_file(MnSim/paul4.txt paul4.txt @COPY_ONLY) + +foreach(file ${TestSourceMnSim}) + get_filename_component(testname ${file} NAME_WE) + ROOT_EXECUTABLE(${testname} ${file} LIBRARIES Minuit2 Minuit2TestMnSim) + ROOT_ADD_TEST(minuit2-${testname} COMMAND ${testname}) +endforeach() + +#for the global tests using ROOT libs (Minuit2 should be taken via the PluginManager) + +set(RootLibraries Core RIO Net Hist Graf Graf3d Gpad Tree + Rint Postscript Matrix Physics MathCore Thread) + +foreach(file ${TestSource}) + get_filename_component(testname ${file} NAME_WE) + ROOT_EXECUTABLE(${testname} ${file} LIBRARIES ${RootLibraries} ) + ROOT_ADD_TEST(minuit2-${testname} COMMAND ${testname}) +endforeach() + + diff --git a/math/cmaes/test/Makefile b/math/cmaes/test/Makefile new file mode 100644 index 0000000000000..189834c4f7331 --- /dev/null +++ b/math/cmaes/test/Makefile @@ -0,0 +1,90 @@ +# Makefile for the ROOT test programs. +# This Makefile shows nicely how to compile and link applications +# using the ROOT libraries on all supported platforms. +# +# Copyright (c) 2000 Rene Brun and Fons Rademakers +# +# Author: Fons Rademakers, 29/2/2000 + +ROOTSYS = ../../.. +include $(ROOTSYS)/etc/Makefile.arch + +#------------------------------------------------------------------------------ + +ifeq ($(PLATFORM),win32) +EXTRALIBS = "$(ROOTSYS)/lib/libcmaesroot.lib" +else +EXTRALIBS = -lcmaesroot -lglog -lgflags +endif + +# for using with MPI +ifneq ($(USE_MPI),) +CXX=mpic++ +LD=mpic++ +endif +ifneq ($(USE_OPENMP),) +CXXFLAGS += -D_GLIBCXX_PARALLEL -fopenmp +LDFLAGS += -fopenmp +endif + + + +USERFUNCOBJ = testUserFunc.$(ObjSuf) +USERFUNCSRC = testUserFunc.$(SrcSuf) +USERFUNC = testUserFunc$(ExeSuf) + +MINIMIZEROBJ = testMinimizer.$(ObjSuf) +MINIMIZERSRC = testMinimizer.$(SrcSuf) +MINIMIZER = testMinimizer$(ExeSuf) + +NDIMFITOBJ = testNdimFit.$(ObjSuf) +NDIMFITSRC = testNdimFit.$(SrcSuf) +NDIMFIT = testNdimFit$(ExeSuf) + +GAUSFITOBJ = testUnbinGausFit.$(ObjSuf) +GAUSFITSRC = testUnbinGausFit.$(SrcSuf) +GAUSFIT = testUnbinGausFit$(ExeSuf) + + +OBJS = $(USERFUNCOBJ) $(GRAPHOBJ) $(MINIMIZEROBJ) $(NDIMFITOBJ) $(GAUSFITOBJ) + +PROGRAMS = $(USERFUNC) $(GRAPH) $(MINIMIZER) $(NDIMFIT) $(GAUSFIT) + +.SUFFIXES: .$(SrcSuf) .$(ObjSuf) $(ExeSuf) + + +all: $(PROGRAMS) + +$(USERFUNC): $(USERFUNCOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(MINIMIZER): $(MINIMIZEROBJ) +ifeq ($(PLATFORM),win32) + $(LD) $(LDFLAGS) $^ $(LIBS) "$(ROOTSYS)/lib/libcmaesroot.lib" $(OutPutOpt)$@ +else + $(LD) $(LDFLAGS) $^ $(LIBS) -lMathCore $(OutPutOpt)$@ +endif + @echo "$@ done" + +$(NDIMFIT): $(NDIMFITOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + +$(GAUSFIT): $(GAUSFITOBJ) + $(LD) $(LDFLAGS) $^ $(LIBS) $(EXTRALIBS) $(OutPutOpt)$@ + @echo "$@ done" + + +clean: + @rm -f $(OBJS) core + +distclean: clean + @rm -f $(PROGRAMS) *Dict.* *.def *.exp \ + *.root *.ps *.so *.lib *.dll *.d .def so_locations + +.SUFFIXES: .$(SrcSuf) + + +.$(SrcSuf).$(ObjSuf): + $(CXX) $(CXXFLAGS) -c $< diff --git a/math/cmaes/test/cmaesFullBench.py b/math/cmaes/test/cmaesFullBench.py new file mode 100644 index 0000000000000..cba3a55f8afbd --- /dev/null +++ b/math/cmaes/test/cmaesFullBench.py @@ -0,0 +1,104 @@ +import sys, csv +import numpy as np +import matplotlib.pyplot as plt +from numpy import * + +datfiles = ["combined.dat","example3D.dat","fit2a.dat","fit2.dat","fit2dhist.dat","gauss2D_fit.dat","gauss_fit.dat","lorentz_fit.dat"] + +fig, axarr = plt.subplots(8,2) + +i = 0 +j = 0 +N = 2 +runs = -1 +for f in datfiles: + dat = loadtxt(f,dtype=float,comments='#') + nalgs = len(dat) + + if runs == -1: + runs = dat[0,3]+dat[0,4] # get the number of runs once. + + hcolor = 'Teal' + aa = 0 + oldrec = None + for a in range(nalgs): + if a == nalgs-1: + hcolor = 'LightGreen' + + aavg1 = [dat[a,2],dat[a,9]] + aastd1 = [0.0,0.0] + aavg2 = [dat[a,5]*1000.0,dat[a,7]] + aastd2 = [dat[a,6]*1000.0,dat[a,8]] + + ## necessary variables + ind = np.arange(N) # the x locations for the groups + width = 0.05 # the width of the bars + + ## the bars + rects1 = axarr[i,j+1].bar(ind+aa*width, aavg1, width, + color=hcolor, + yerr=aastd1, + error_kw=dict(elinewidth=2,ecolor='red')) + if a == 0: + oldrec = rects1 + + #rects2 = ax2.bar(ind+width, minAvg, width, + # color='LightGreen', + # yerr=minStd, + # error_kw=dict(elinewidth=2,ecolor='black')) + + rects12 = axarr[i,j].bar(ind+aa*width, aavg2, width, + color=hcolor, + yerr=aastd2, + error_kw=dict(elinewidth=2,ecolor='red')) + + #rects22 = axarr[i,j].bar(ind+width, minAvg2, width, + # color='LightGreen', + # yerr=minStd2, + # error_kw=dict(elinewidth=2,ecolor='black')) + + #add a legend + if i == 6: + axarr[6,1].legend((oldrec[0], rects12[0]), ('aCMA-ES', 'Minuit2'), fontsize=10 ) + aa = aa + 1 + + + + # axes and labels + axarr[i,j].set_yscale("log",nonposy='clip') + #axarr[i,j].set_xlim(-width,len(ind)+width) + axarr[i,j].set_ylim(0) + #axarr[i,j+1].set_xlim(-width,len(ind)+width) + axarr[i,j+1].set_ylim(top=runs) + if i == 4 or i == 6: + axarr[i,j+1].set_ylim(top=2*runs) + if i == 7: + axarr[i,j+1].set_ylim(top=100) + #axarr[i,j].set_ylabel('Scores') + axarr[i,j].set_title(f + " / " + str(dat[0,0]) + "-D",fontsize=12) + #axarr[i,j].set_xticks(ind+width) + #axarr[i,j+1].set_xticks(ind+width) + plt.setp(axarr[i,j].get_xticklabels(),visible=False) + plt.setp(axarr[i,j+1].get_xticklabels(),visible=False) + if i == 7: + xTickMarks1 = ["CPU avg (ms)","","","","","Budget avg"] + xTickMarks2 = ["Found","","","","","wins"] + xtickNames = axarr[7,j].set_xticklabels(xTickMarks1) + plt.setp(xtickNames, rotation=45, fontsize=10) + xtickNames2 = axarr[7,j+1].set_xticklabels(xTickMarks2) + plt.setp(xtickNames2, rotation=45, fontsize=10) + plt.setp(axarr[i,j].get_xticklabels(),visible=True) + plt.setp(axarr[i,j+1].get_xticklabels(),visible=True) + + #add a legend +# if i == 6: +# axarr[7,1].legend()# (rects1[0], rects12[0]), ('aCMA-ES', 'Minuit2'), fontsize=10 ) + i = i + 1 + j = 0 +# if i == 2: +# i = 0 +# j = j + 1 + +#plt.tight_layout() +plt.suptitle('aCMA-ES / Minuit2 Benchmark Suite / ' + str(len(datfiles)) + ' experiments / ' + str(int(runs)) + ' runs on each\nlambda={auto, 50, 200, auto-aipop-4-restarts, auto-abipop-10-restarts}') #10, 20, 40, 80, 160, 320, 640, 1280}') +plt.show() diff --git a/math/cmaes/test/testMinimizer.cxx b/math/cmaes/test/testMinimizer.cxx new file mode 100644 index 0000000000000..dc42368a9dbff --- /dev/null +++ b/math/cmaes/test/testMinimizer.cxx @@ -0,0 +1,891 @@ +// test of minimization using new minimizer classes + +#include "Math/Minimizer.h" +#include "Math/Factory.h" +#include "Math/Functor.h" + +#include "TVirtualFitter.h" +#include "TSystem.h" + +#include "Math/IFunction.h" +#include "Math/Util.h" +#include +#include + +#include +#include + +#include "TStopwatch.h" +#include "TMatrixD.h" +#include "TVectorD.h" +#include "TRandom3.h" +#include "TMath.h" + +//#define DEBUG + +int gNCall = 0; +int gNCall2 = 0; +int gNmin = 1000; +int gVerbose = 0; +bool useGradient = true; + +bool minos = true; + +double gAbsTolerance = 0.005; + +// Rosenbrok function to be minimize + +typedef void (*FCN)(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag); + + + +// ROSENBROCK function +//______________________________________________________________________________ +void RosenBrock(Int_t &, Double_t *, Double_t &f, Double_t *par, Int_t /*iflag*/) +{ + gNCall++; + const Double_t x = par[0]; + const Double_t y = par[1]; + const Double_t tmp1 = y-x*x; + const Double_t tmp2 = 1-x; + f = 100*tmp1*tmp1+tmp2*tmp2; +} + + + +class RosenBrockFunction : public ROOT::Math::IMultiGenFunction { + +public : + + virtual ~RosenBrockFunction() {} + + unsigned int NDim() const { return 2; } + + ROOT::Math::IMultiGenFunction * Clone() const { + return new RosenBrockFunction(); + } + + const double * TrueMinimum() const { + fTrueMin[0] = 1; + fTrueMin[1] = 1; + return fTrueMin; + } + + private: + + inline double DoEval (const double * x) const { +#ifdef USE_FREE_FUNC + double f = 0; + int ierr = 0; + int i = 0; + RosenBrock(i,0,f,const_cast(x),ierr); + return f; +#else + gNCall++; + const Double_t xx = x[0]; + const Double_t yy = x[1]; + const Double_t tmp1 = yy-xx*xx; + const Double_t tmp2 = 1-xx; + return 100*tmp1*tmp1+tmp2*tmp2; +#endif + } + + + mutable double fTrueMin[2]; +}; + + +// TRIGONOMETRIC FLETCHER FUNCTION + +class TrigoFletcherFunction : public ROOT::Math::IMultiGradFunction { + +public : + + + TrigoFletcherFunction(unsigned int dim) : fDim(dim) { + double seed = 3; + A.ResizeTo(dim,dim); + B.ResizeTo(dim,dim); + x0.ResizeTo(dim); + sx0.ResizeTo(dim); + cx0.ResizeTo(dim); + sx.ResizeTo(dim); + cx.ResizeTo(dim); + v0.ResizeTo(dim); + v.ResizeTo(dim); + r.ResizeTo(dim); + A.Randomize(-100.,100,seed); + B.Randomize(-100.,100,seed); + for (unsigned int i = 0; i < dim; i++) { + for (unsigned int j = 0; j < dim; j++) { + A(i,j) = int(A(i,j)); + B(i,j) = int(B(i,j)); + } + } + x0.Randomize(-TMath::Pi(),TMath::Pi(),seed); + // calculate vector Ei + for (unsigned int i = 0; i < fDim ; ++i) { + cx0[i] = std::cos(x0[i]); + sx0[i] = std::sin(x0[i]); + } + v0 = A*sx0+B*cx0; + } + + + unsigned int NDim() const { return fDim; } + + ROOT::Math::IMultiGenFunction * Clone() const { + TrigoFletcherFunction * f = new TrigoFletcherFunction(*this); +// std::cerr <<"cannot clone this function" << std::endl; +// assert(0); + return f; + } + + + void StartPoints(double * x, double * s) { + TRandom3 rndm; + const double stepSize = 0.01; + const double deltaAmp = 0.1; + const double pi = TMath::Pi(); + for (unsigned int i = 0; i < fDim; ++i) { + double delta = rndm.Uniform(-deltaAmp*pi,deltaAmp*pi); + x[i] = x0(i) + 0.1*delta; + if (x[i] <= - pi) x[i] += 2.*pi; + if (x[i] > pi) x[i] -= 2.*pi; + s[i] = stepSize; + } + } + + + const double * TrueMinimum() const { + return x0.GetMatrixArray(); + } + + + void Gradient (const double * x, double * g) const { + gNCall2++; + + for (unsigned int i = 0; i < fDim ; ++i) { + cx [i] = std::cos(x[i]); + sx [i] = std::sin(x[i]); + } + + v = A*sx +B*cx; + r = v0-v; + + + // calculate the grad components + for (unsigned int i = 0; i < fDim ; ++i) { + g[i] = 0; + for (unsigned int k = 0; k < fDim ; ++k) { + g[i] += 2. * r(k) * ( - A(k,i) * cx(i) + B(k,i) * sx(i) ); + } + } + + } + +#ifdef USE_FDF + void FdF (const double * x, double & f, double * g) const { + gNCall++; + + for (unsigned int i = 0; i < fDim ; ++i) { + cx [i] = std::cos(x[i]); + sx [i] = std::sin(x[i]); + } + + v = A*sx +B*cx; + r = v0-v; + + f = r * r; + + + // calculate the grad components + for (unsigned int i = 0; i < fDim ; ++i) { + g[i] = 0; + for (unsigned int k = 0; k < fDim ; ++k) { + g[i] += 2. * r(k) * ( - A(k,i) * cx(i) + B(k,i) * sx(i) ); + } + } + } +#endif + + private: + +// TrigoFletcherFunction(const TrigoFletcherFunction & ) {} +// TrigoFletcherFunction & operator=(const TrigoFletcherFunction &) { return *this; } + + double DoEval (const double * x) const { + gNCall++; + + + for (unsigned int i = 0; i < fDim ; ++i) { + cx [i] = std::cos(x[i]); + sx [i] = std::sin(x[i]); + } + + v = A*sx +B*cx; + r = v0-v; + + return r * r; + } + + + double DoDerivative (const double * x, unsigned int i ) const { + std::vector g(fDim); + Gradient(x,&g[0]); + return g[i]; + } + +private: + + unsigned int fDim; + + TMatrixD A; + TMatrixD B; + TVectorD x0; + mutable TVectorD sx0; + mutable TVectorD cx0; + mutable TVectorD sx; + mutable TVectorD cx; + mutable TVectorD v0; + mutable TVectorD v; + mutable TVectorD r; + + +}; + + +// CHEBYQUAD FUNCTION + +class ChebyQuadFunction : public ROOT::Math::IMultiGradFunction { + +public : + + ChebyQuadFunction(unsigned int n) : + fDim(n), + fvec(std::vector(n) ), + fTrueMin(std::vector(n) ) + { + } + + unsigned int NDim() const { return fDim; } + + ROOT::Math::IMultiGenFunction * Clone() const { + return new ChebyQuadFunction(*this); + } + + const double * TrueMinimum() const { + return &fTrueMin[0]; + } + + // use equally spaced points + void StartPoints(double * x, double * s) { + for (unsigned int i = 0; i < fDim; ++i) { + s[i] = 0.01; + x[i] = double(i)/(double(fDim)+1.0); + } + } + + // compute gradient + + void Gradient(const double * x, double * g) const { + gNCall2++; + unsigned int n = fDim; + // estimate first the fvec + DoCalculatefi(x); + + for (unsigned int j = 0; j < n; ++j) { + g[j] = 0.0; + double t1 = 1.0; + double t2 = 2.0 * x[j] - 1.0; + double t = 2.0 * t2; + double s1 = 0.0; + double s2 = 2.0; + for (unsigned int i = 0; i < n; ++i) { + g[j] += fvec[i] * s2; + double th = 4.0 * t2 + t * s2 - s1; + s1 = s2; + s2 = th; + th = t * t2 - t1; + t1 = t2; + t2 = th; + } + g[j] = 2. * g[j] / double(n); + } + + + } + + private: + + double DoEval (const double * x) const { + + gNCall++; + DoCalculatefi(x); + double f = 0; + for (unsigned int i = 0; i < fDim; ++i) + f += fvec[i] * fvec[i]; + + return f; + + } + + double DoDerivative (const double * x, unsigned int i ) const { + std::vector g(fDim); + Gradient(x,&g[0]); + return g[i]; + } + + void DoCalculatefi(const double * x) const { + // calculate the i- element ; F(X) = Sum {fi] + unsigned int n = fDim; + for (unsigned int i = 0; i < n; ++i) + fvec[i] = 0; + + for (unsigned int j = 0; j < n; ++j) { + double t1 = 1.0; + double t2 = 2.0 * x[j] - 1.0; + double t = 2.0 * t2; + for (unsigned int i = 0; i < n; ++i) { + fvec[i] += t2; + double th = t * t2 - t1; + t1 = t2; + t2 = th; + } + } + + // sum with the integral (integral is zero for odd Cheb polynomial and = 1/(i**2 -1) for the even ones + for (unsigned int i = 1; i <= n; ++i) { + int l = i-1; + fvec[l] /= double ( n ); + if ( ( i % 2 ) == 0 ) { + fvec[l] += 1.0 / ( double ( i*i ) - 1.0 ); + } + } + } + + unsigned int fDim; + mutable std::vector fvec; + mutable std::vector fTrueMin; +}; + +//WOOD function (4 dim function) + +double WoodFunction(const double * par) { + gNCall++; + + const double w = par[0]; + const double x = par[1]; + const double y = par[2]; + const double z = par[3]; + + const double w1 = w-1; + const double x1 = x-1; + const double y1 = y-1; + const double z1 = z-1; + const double tmp1 = x-w*w; + const double tmp2 = z-y*y; + + double f = 100*tmp1*tmp1+w1*w1+90*tmp2*tmp2+y1*y1+10.1*(x1*x1+z1*z1)+19.8*x1*z1; + return f; +} + +//Powell Function (4 dim function) +double PowellFunction(const double * par) { + gNCall++; + + const double w = par[0]; + const double x = par[1]; + const double y = par[2]; + const double z = par[3]; + + const double tmp1 = w+10*x; + const double tmp2 = y-z; + const double tmp3 = x-2*y; + const double tmp4 = w-z; + + double f = tmp1*tmp1+5*tmp2*tmp2+tmp3*tmp3*tmp3*tmp3+10*tmp4*tmp4*tmp4*tmp4; + return f; +} + +double SimpleQuadFunction(const double * par) { + gNCall++; + double x = par[0]; + double y = par[1]; + double f = x * x + 2 * y * y - x*y; + std::cout << "Quadfunc " << gNCall << "\t" << x << " , " << y << " f = " << f << std::endl; + return f; +} + +const double * TrueMinimum(const ROOT::Math::IMultiGenFunction & func) { + + const RosenBrockFunction * fRB = dynamic_cast< const RosenBrockFunction *> (&func); + if (fRB != 0) return fRB->TrueMinimum(); + const TrigoFletcherFunction * fTF = dynamic_cast< const TrigoFletcherFunction *> (&func); + if (fTF != 0) return fTF->TrueMinimum(); +// const ChebyQuadFunction * fCQ = dynamic_cast< const ChebyQuadFunction *> (&func); +// if (fCQ != 0) return fCQ->TrueMinimum(); + return 0; +} + +void printMinimum(const std::vector & x) { + std::cout << "Minimum X values\n"; + std::cout << "\t"; + int pr = std::cout.precision(12); + unsigned int n = x.size(); + for (unsigned int i = 0; i < n; ++i) { + std::cout << x[i]; + if ( i != n-1 ) std::cout << " , "; + if ( i > 0 && i % 6 == 0 ) std::cout << "\n\t"; + } + std::cout << std::endl; + std::cout.precision(pr); +} + +int DoNewMinimization( const ROOT::Math::IMultiGenFunction & func, const double * x0, const double * s0, ROOT::Math::Minimizer * min, double &minval, double &edm, double * minx) { + + int iret = 0; + + min->SetMaxFunctionCalls(1000000); + min->SetMaxIterations(100000); + min->SetTolerance(gAbsTolerance); + if (func.NDim() >= 10) { + min->SetTolerance(0.01); + + } + + min->SetPrintLevel(gVerbose); + // check if func provides gradient + const ROOT::Math::IMultiGradFunction * gfunc = dynamic_cast(&func); + if (gfunc != 0 && useGradient) + min->SetFunction(*gfunc); + else + min->SetFunction(func); + + for (unsigned int i = 0; i < func.NDim(); ++i) { +#ifdef DEBUG + std::cout << "set variable " << i << " to value " << x0[i] << std::endl; +#endif + min->SetVariable(i,"x" + ROOT::Math::Util::ToString(i),x0[i], s0[i]); + } + + bool ret = min->Minimize(); + minval = min->MinValue(); + edm = min->Edm(); + + if (!ret) { + return -1; + } + + const double * xmin = min->X(); + + bool ok = true; + const double * trueMin = TrueMinimum(func); + if (trueMin != 0) { + for (unsigned int i = 0; i < func.NDim(); ++i) + ok &= (std::fabs(xmin[i]-trueMin[i] ) < gAbsTolerance); + } + + if (!ok) iret = -2; + int ncall_migrad = gNCall; + + // test Minos (use the default up of 1) + if (minos) { + + double el,eu; + for (unsigned int i = 0; i < func.NDim(); ++i) { + ret = min->GetMinosError(i,el,eu); + std::cout << "ncalls " << gNCall << "\t"; + if (ret) std::cout << "MINOS error for " << i << " = " << el << " " << eu << std::endl; + else std::cout << "MINOS failed for " << i << std::endl; + } + } + + std::cout << "\nMigrad Ncalls:\t " << ncall_migrad << std::endl; + std::cout << "Minos Ncalls :\t " << gNCall - ncall_migrad << std::endl; + + +// std::cout << "function at the minimum " << func(xmin) << std::endl; + std::copy(xmin,xmin+func.NDim(),minx); + min->Clear(); + + return iret; +} + +int DoOldMinimization( FCN func, TVirtualFitter * min, double &minval, double &edm) { + + int iret = 0; + + assert(min != 0); + min->SetFCN( func ); + + Double_t arglist[100]; + arglist[0] = gVerbose-1; + min->ExecuteCommand("SET PRINT",arglist,1); + + min->SetParameter(0,"x",-1.2,0.01,0,0); + min->SetParameter(1,"y", 1.0,0.01,0,0); + + arglist[0] = 0; + min->ExecuteCommand("SET NOW",arglist,0); + arglist[0] = 1000; // number of function calls + arglist[1] = gAbsTolerance; // tolerance + //min->ExecuteCommand("MIGRAD",arglist,0); + min->ExecuteCommand("MIGRAD",arglist,2); + + if (minos) min->ExecuteCommand("MINOS",arglist,0); + + Double_t parx,pary; + Double_t we,al,bl; + Char_t parName[32]; + min->GetParameter(0,parName,parx,we,al,bl); + min->GetParameter(1,parName,pary,we,al,bl); + + bool ok = ( TMath::Abs(parx-1.) < gAbsTolerance && + TMath::Abs(pary-1.) < gAbsTolerance ); + + + double errdef = 0; + int nvpar, nparx; + min->GetStats(minval,edm,errdef,nvpar,nparx); + if (!ok) iret = -2; + + min->Clear(); // for further use + return iret; + +} + + +int testNewMinimizer( const ROOT::Math::IMultiGenFunction & func, const double * x0, const double * s0, const std::string & minimizer, const std::string & algoType) { + + std::cout << "\n************************************************************\n"; + std::cout << "\tTest new ROOT::Math::Minimizer\n"; + std::cout << "\tMinimizer is " << minimizer << " " << algoType << std::endl; + + int iret = 0; + double minval,edm = 0; + std::vector xmin(func.NDim() ); + + TStopwatch w; + w.Start(); + + ROOT::Math::Minimizer * min = ROOT::Math::Factory::CreateMinimizer(minimizer, algoType); + if (min == 0) { + std::cout << "Error using minimizer " << minimizer << " " << algoType << std::endl; + return -1; + } + + + for (int i = 0; i < gNmin; ++i) { + gNCall = 0; gNCall2 = 0; + iret |= DoNewMinimization(func, x0, s0, min,minval,edm,&xmin[0]); + } + + w.Stop(); + if (iret != 0) std::cout << "\n****** ERROR: Minimization FAILED ! \n"; + int pr = std::cout.precision(18); + std::cout << "\nNCalls: \t" << gNCall << " , " << gNCall2 + << "\tMinValue: \t" << minval << "\tEdm: \t" << edm; std::cout.precision(pr); + std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl; + printMinimum(xmin ); + std::cout << "\n************************************************************\n"; + +#ifdef CHECK_WITHMINUIT + // do Minuit after BFGS + if (minimizer == "GSL_BFGS") { + std::cout << "DO cmaes from last point\n"; + gNCall = 0; + iret |= DoNewMinimization(func, &xmin.front(), s0, "cmaes","",minval,edm,&xmin[0]); + int pr = std::cout.precision(18); + std::cout << "\nNCalls: \t" << gNCall << "\tMinValue: \t" << minval << "\tEdm: \t" << edm; std::cout.precision(pr); + std::cout << std::endl; + } +#endif + + delete min; + + return iret; +} + + +int testOldMinimizer( FCN func, const std::string & fitter, int n=25) { + + std::cout << "\n************************************************************\n"; + std::cout << "\tTest using TVirtualFitter\n"; + std::cout << "\tFitter is " << fitter << std::endl; + + int iret = 0; + double minval,edm = 0; + + TStopwatch w; + w.Start(); + + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + + TVirtualFitter *min = TVirtualFitter::Fitter(0,n); + + //min->Dump(); + + for (int i = 0; i < gNmin; ++i) { + gNCall = 0; + iret |= DoOldMinimization(func, min,minval,edm); + } + + w.Stop(); + if (iret != 0) std::cout << "\n****** ERROR: Minimization FAILED ! \n"; + int pr = std::cout.precision(18); + std::cout << "\nNCalls: \t" << gNCall << "\tMinValue: \t" << minval << "\tEdm: \t" << edm; std::cout.precision(pr); + std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl; + std::cout << "\n************************************************************\n"; + + return iret; +} + +int testRosenBrock() { + + int iret = 0; + + + std::cout << "\n************************************************************\n"; + std::cout << "\tROSENBROCK function test\n\n"; + + double s0[2] = {0.01,0.01}; + + // minimize using Rosenbrock Function +#ifndef DEBUG + gNmin = 2000; +#endif + + gNmin = 1; + + + RosenBrockFunction fRB; + double xRB[2] = { -1.,1.2}; + + iret |= testNewMinimizer(fRB,xRB,s0,"Minuit",""); + iret |= testNewMinimizer(fRB,xRB,s0,"cmaes",""); + +// iret |= testNewMinimizer(fRB,xRB,s0,"GSLMultiMin","ConjugateFR"); +// iret |= testNewMinimizer(fRB,xRB,s0,"GSLMultiMin","ConjugatePR"); +// iret |= testNewMinimizer(fRB,xRB,s0,"GSLMultiMin","BFGS"); +// iret |= testNewMinimizer(fRB,xRB,s0,"GSLMultiMin","BFGS2"); + +// iret |= testOldMinimizer(RosenBrock,"Minuit",2); +// iret |= testOldMinimizer(RosenBrock,"cmaes",2); + + + return iret; +} + + +int testChebyQuad() { + + int iret = 0; + + // test with ChebyQuad function + + const int n = 8; + ChebyQuadFunction func(n); + +#ifndef DEBUG + gNmin = std::max(1, int(20000/n/n) ); +#endif + gNmin = 1; + + + double s0[n]; + double x0[n]; + func.StartPoints(x0,s0); + + std::cout << "\n************************************************************\n"; + std::cout << "\tCHEBYQUAD function test , n = " << n << "\n\n"; + + +// double x[8] = {0.043153E+00, 0.193091E+00, 0.266329E+00, 0.500000E+00, +// 0.500000E+00, 0.733671E+00, 0.806910E+00, 0.956847E+00 }; +// double x[2] = {0.5, 0.5001}; +// std::cout << "FUNC " << func(x) << std::endl; + double x1[100] = { 0.00712780070646 , 0.0123441993113 , 0.0195428378255 , 0.0283679084192 , 0.0385291131289 , 0.0492202424892 , 0.0591277976178 , + 0.0689433195252 , 0.0791293590525 , 0.088794974369 , 0.0988949579193 , 0.108607151294 , 0.118571075831 , + 0.128605446238 , 0.137918291068 , 0.149177761352 , 0.156665324587 , 0.170851061982 , 0.174688134016 , + 0.192838903364 , 0.193078270803 , 0.209255377225 , 0.217740096779 , 0.225888518345 , 0.241031047421 , + 0.244253844041 , 0.257830449676 , 0.269467652526 , 0.274286498012 , 0.288877029988 , 0.297549406597 , + 0.304950954529 , 0.319230811642 , 0.326387092206 , 0.335229058731 , 0.349178359226 , 0.355905988048 , + 0.365197862755 , 0.379068092603 , 0.385826036925 , 0.394978252826 , 0.408974425717 , 0.415968185065 , + 0.424621041584 , 0.438837361714 , 0.446214149031 , 0.454242324351 , 0.468614308013 , 0.476506553416 , + 0.483916944941 , 0.498229247409 , 0.506794629616 , 0.513736742474 , 0.527712475478 , 0.537073277673 , + 0.543731917673 , 0.557187513963 , 0.567346279639 , 0.57379846397 , 0.586691058785 , 0.597561941009 , + 0.60382873461 , 0.616316037506 , 0.627719652101 , 0.633760038662 , 0.646175283836 , 0.657809344891 , + 0.663569004722 , 0.676314563639 , 0.687674566849 , 0.69332205923 , 0.706839545953 , 0.716907408637 , + 0.723407327715 , 0.738019389561 , 0.744806584048 , 0.754657613362 , 0.769181875619 , 0.772250323489 , + 0.787104833193 , 0.795856360905 , 0.804099304478 , 0.82142178741 , 0.819589601284 , 0.839024540481 , + 0.842457233039 , 0.857393475964 , 0.86408033345 , 0.876329840525 , 0.884867318008 , 0.895744532071 , + 0.905113958163 , 0.915445338697 , 0.925148068352 , 0.935344457785 , 0.945127838313 , 0.955272197168 , + 0.965687518559 , 0.975129521484 , 0.982662007764 }; + + std::cout << "FUNC " << func(x1) << std::endl; + + + iret |= testNewMinimizer(func,x0,s0, "Minuit",""); + iret |= testNewMinimizer(func,x0,s0, "cmaes",""); + +// iret |= testNewMinimizer(func,x0,s0, "GSLMultiMin","ConjugateFR"); +// iret |= testNewMinimizer(func,x0,s0, "GSLMultiMin","ConjugatePR"); +// iret |= testNewMinimizer(func,x0,s0, "GSLMultiMin","BFGS"); + + return iret; +} + + +int testTrigoFletcher() { + + int iret = 0; + + + // test with fletcher trigonometric function +#ifndef DEBUG + gNmin = 2; +#endif + gNmin = 1; + + const int nT = 50; + TrigoFletcherFunction fTrigo(nT); + double sTrigo[nT]; + double xTrigo[nT]; + fTrigo.StartPoints(xTrigo,sTrigo); + + std::cout << "\n************************************************************\n"; + std::cout << "\tTRIGONOMETRIC Fletcher function test , n = " << nT << "\n\n"; + + + iret |= testNewMinimizer(fTrigo,xTrigo,sTrigo,"cmaes",""); + iret |= testNewMinimizer(fTrigo,xTrigo,sTrigo,"Minuit",""); + +// iret |= testNewMinimizer(fTrigo,xTrigo,sTrigo,"GSLMultiMin","ConjugateFR"); +// iret |= testNewMinimizer(fTrigo,xTrigo,sTrigo,"GSLMultiMin","ConjugatePR"); +// iret |= testNewMinimizer(fTrigo,xTrigo,sTrigo,"GSLMultiMin","BFGS"); + + + return iret; +} + + +int testWood() { + + int iret = 0; + + + // test with Wood function (4d) +// minimum : F(1,1,1,1) = 0. + + +#ifndef DEBUG + gNmin = 1000; +#endif + gNmin = 1; + + ROOT::Math::Functor f(&WoodFunction,4); + + double x0[4] = { -3, -1, -3, -1 }; + double s0[4] = { 0.1, 0.1, 0.1, 0.1}; + + std::cout << "\n************************************************************\n"; + std::cout << "\tWOOD 4 function test \n\n"; + + + iret |= testNewMinimizer(f, x0, s0,"Minuit",""); + iret |= testNewMinimizer(f, x0, s0,"cmaes",""); + + + return iret; +} + +int testPowell() { + + int iret = 0; + + + // test with Powell function (4d) + // minimum is at F(0,0,0,0) = 0 +#ifndef DEBUG + gNmin = 1000; +#endif + gNmin = 1; + + ROOT::Math::Functor f(&PowellFunction,4); + + double x0[4] = { -3, -1, 0, 1 }; + double s0[4] = { 0.1, 0.1, 0.1, 0.1}; + + std::cout << "\n************************************************************\n"; + std::cout << "\tPOWELL function test \n\n"; + + + iret |= testNewMinimizer(f, x0, s0,"Minuit",""); + iret |= testNewMinimizer(f, x0, s0,"cmaes",""); + + + return iret; +} + + +int testQuadFunc() { + + int iret = 0; + + + // test with a simple quadratic function 2d + // minimum is at F(0,0) = 0 +#ifndef DEBUG + gNmin = 1000; +#endif + gNmin = 1; + + ROOT::Math::Functor f(&SimpleQuadFunction,2); + + double x0[4] = { -3, -3 }; + double s0[4] = { 0.1, 0.1}; + + std::cout << "\n************************************************************\n"; + std::cout << "\tSIMPLE QUAD function test \n\n"; + + + iret |= testNewMinimizer(f, x0, s0,"Minuit",""); + iret |= testNewMinimizer(f, x0, s0,"cmaes",""); + + + return iret; +} + + +int main() { + + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + + int iret = 0; + +#ifdef DEBUG + gVerbose = 4; + gNmin = 1; +#endif + + + iret |= testRosenBrock(); + iret |= testChebyQuad(); + iret |= testTrigoFletcher(); + + iret |= testWood(); + iret |= testPowell(); + + iret |= testQuadFunc(); + + + + if (iret != 0) + std::cerr << "testMinim :\t FAILED " << std::endl; + else + std::cerr << "testMinim :\t OK " << std::endl; + return iret; + +} diff --git a/math/cmaes/test/testNdimFit.cxx b/math/cmaes/test/testNdimFit.cxx new file mode 100644 index 0000000000000..b3cecc526f12d --- /dev/null +++ b/math/cmaes/test/testNdimFit.cxx @@ -0,0 +1,285 @@ +#include "TMath.h" +#include "TSystem.h" +#include "TRandom3.h" +#include "TTree.h" +#include "TROOT.h" + +#include "Fit/UnBinData.h" +#include "Fit/Fitter.h" + + +#include "Math/IParamFunction.h" +#include "Math/WrappedTF1.h" +#include "Math/WrappedMultiTF1.h" +#include "Math/WrappedParamFunction.h" +#include "Math/MultiDimParamFunctionAdapter.h" + +#include "TGraphErrors.h" + +#include "TStyle.h" + + +#include "Math/DistFunc.h" + +#include +#include + +#include "TStopwatch.h" + +#define DEBUG + +// test fit with many dimension + +const int N = 10; +const std::string branchType = "x[10]/D"; +const int NPoints = 100000; + +// const int N = 50; +// const std::string branchType = "x[50]/D"; +// const int NPoints = 10000; + + + +double truePar[2*N]; +double iniPar[2*N]; +//const int nfit = 1; +const int strategy = 0; + +double gausnorm(const double *x, const double *p) { + + double invsig = 1./p[1]; + double tmp = (x[0]-p[0]) * invsig; + const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 ); + return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig; +} + +double gausnormN(const double *x, const double *p) { + double f = 1; + for (int i = 0; i < N; ++i) + f *= gausnorm(x+i,p+2*i); + + return f; +} + +struct CMAES { + static std::string name() { return "cmaes"; } + static std::string name2() { return "acmaes"; } +}; + +// fill fit data structure +ROOT::Fit::UnBinData * FillUnBinData(TTree * tree ) { + + // fill the unbin data set from a TTree + ROOT::Fit::UnBinData * d = 0; + + // for the large tree access directly the branches + d = new ROOT::Fit::UnBinData(); + + unsigned int n = tree->GetEntries(); +#ifdef DEBUG + std::cout << "number of unbin data is " << n << " of dim " << N << std::endl; +#endif + d->Initialize(n,N); + TBranch * bx = tree->GetBranch("x"); + double vx[N]; + bx->SetAddress(vx); + std::vector m(N); + for (int unsigned i = 0; i < n; ++i) { + bx->GetEntry(i); + d->Add(vx); + for (int j = 0; j < N; ++j) + m[j] += vx[j]; + } + +#ifdef DEBUG + std::cout << "average values of means :\n"; + for (int j = 0; j < N; ++j) + std::cout << m[j]/n << " "; + std::cout << "\n"; +#endif + + delete tree; + tree = 0; + return d; + +} + + +// unbin fit + +typedef ROOT::Math::IParamMultiFunction Func; +template +int DoUnBinFit(T * tree, Func & func, bool debug = false ) { + + ROOT::Fit::UnBinData * d = FillUnBinData(tree ); + // need to have done Tree->Draw() before fit + //FillUnBinData(d,tree); + + //std::cout << "data size type and size is " << typeid(*d).name() << " " << d->Size() << std::endl; + std::cout << "Fit data size = " << d->Size() << " dimension = " << d->NDim() << std::endl; + + + + //printData(d); + + // create the fitter + //std::cout << "Fit parameter 2 " << f.Parameters()[2] << std::endl; + + ROOT::Fit::Fitter fitter; + fitter.Config().SetMinimizer(MinType::name().c_str(),MinType::name2().c_str()); + + if (debug) + fitter.Config().MinimizerOptions().SetPrintLevel(3); + else + fitter.Config().MinimizerOptions().SetPrintLevel(0); + + // set tolerance 1 for tree to be same as in TTTreePlayer::UnBinFIt + fitter.Config().MinimizerOptions().SetTolerance(1); + + // set strategy (0 to avoid MnHesse + fitter.Config().MinimizerOptions().SetStrategy(strategy); + + + // create the function + + fitter.SetFunction(func); + // need to fix param 0 , normalization in the unbinned fits + //fitter.Config().ParSettings(0).Fix(); + + bool ret = fitter.Fit(*d); + if (!ret) { + std::cout << " Fit Failed " << std::endl; + return -1; + } + if (debug) + fitter.Result().Print(std::cout); + + // check fit result + double chi2 = 0; + for (int i = 0; i < N; ++i) { + double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) ); + chi2 += d*d; + } + double prob = ROOT::Math::chisquared_cdf_c(chi2,N); + int iret = (prob < 1.0E-6) ? -1 : 0; + if (iret != 0) { + std::cout <<"Found difference in fitted values - prob = " << prob << std::endl; + if (!debug) fitter.Result().Print(std::cout); + for (int i = 0; i < N; ++i) { + double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) ); + std::cout << "par_" << i << " = " << fitter.Result().Value(i) << " true = " << truePar[i] << " pull = " << d << std::endl; + } + + } + + delete d; + + return iret; + +} + + +template +int DoFit(TTree * tree, Func & func, bool debug = false ) { + return DoUnBinFit(tree, func, debug); +} +// template +// int DoFit(TH1 * h1, Func & func, bool debug = false, bool copyData = false ) { +// return DoBinFit(h1, func, debug, copyData); +// } +// template +// int DoFit(TGraph * gr, Func & func, bool debug = false, bool copyData = false ) { +// return DoBinFit(gr, func, debug, copyData); +// } + +template +int FitUsingNewFitter(FitObj * fitobj, Func & func ) { + + std::cout << "\n************************************************************\n"; + std::cout << "\tFit using new Fit::Fitter " << typeid(*fitobj).name() << std::endl; + std::cout << "\tMinimizer is " << MinType::name() << " " << MinType::name2() << " func dim = " << func.NDim() << std::endl; + + int iret = 0; + TStopwatch w; w.Start(); + +#ifdef DEBUG + std::cout << "initial Parameters " << iniPar << " " << *iniPar << " " << *(iniPar+1) << std::endl; + func.SetParameters(iniPar); + iret |= DoFit(fitobj,func,true ); + +#else + for (int i = 0; i < nfit; ++i) { + func.SetParameters(iniPar); + iret = DoFit(fitobj,func, false); + if (iret != 0) { + std::cout << "Fit failed " << std::endl; + break; + } + } +#endif + w.Stop(); + std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl; + std::cout << "\n************************************************************\n"; + + return iret; +} + + +int testNdimFit() { + + + std::cout << "\n\n************************************************************\n"; + std::cout << "\t UNBINNED TREE (GAUSSIAN MULTI-DIM) FIT\n"; + std::cout << "************************************************************\n"; + + TTree * t1 = new TTree("t2","a large Tree with gaussian variables"); + double x[N]; + Int_t ev; + t1->Branch("x",x,branchType.c_str()); + t1->Branch("ev",&ev,"ev/I"); + + // generate the true parameters + for (int j = 0; j < N; ++j) { + double mu = double(j)/10.; + double s = 1.0 + double(j)/10.; + truePar[2*j] = mu; + truePar[2*j+1] = s; + } + + + //fill the tree + TRandom3 r; + for (Int_t i=0;iFill(); + + } + //t1.Draw("x"); // to select fit variable + + + for (int i = 0; i f2(&gausnormN,N,2*N,iniPar); + + int iret = 0; + iret |= FitUsingNewFitter(t1,f2); + + return iret; +} + +int main() { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + return testNdimFit(); +} diff --git a/math/cmaes/test/testUnbinGausFit.cxx b/math/cmaes/test/testUnbinGausFit.cxx new file mode 100644 index 0000000000000..9192ac50dc8fa --- /dev/null +++ b/math/cmaes/test/testUnbinGausFit.cxx @@ -0,0 +1,333 @@ +#include "TMath.h" +#include "TSystem.h" +#include "TRandom3.h" +#include "TTree.h" +#include "TROOT.h" + +#include "Fit/UnBinData.h" +#include "Fit/Fitter.h" + + +#include "Math/IParamFunction.h" +#include "Math/WrappedTF1.h" +#include "Math/WrappedMultiTF1.h" +#include "Math/WrappedParamFunction.h" +#include "Math/MultiDimParamFunctionAdapter.h" + +#include "TGraphErrors.h" + +#include "TStyle.h" + + +#include "Math/DistFunc.h" + +#include +#include + +#include "TStopwatch.h" + +#define DEBUG + +// test fit with many dimension + +const int N = 1; // 1d fit +const int NGaus = 3; +const int NPar = 8; // sum of 3 gaussians +const std::string branchType = "x[1]/D"; + +// for 8 core testing use 1M points +const int NPoints = 100000; +double truePar[NPar]; +double iniPar[NPar]; +//const int nfit = 1; +const int strategy = 0; + +double gausnorm(const double *x, const double *p) { + + double invsig = 1./std::abs(p[1]); + double tmp = (x[0]-p[0]) * invsig; + const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 ); + return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig; +} + +double gausSum(const double *x, const double *p) { + + double f = gausnorm(x,p+2) + + p[0] * gausnorm(x,p+4) + + p[1] * gausnorm(x,p+6); + + double norm = 1. + p[0] + p[1]; + return f/norm; +} + +struct CMAES { + static std::string name() { return "cmaes"; } + static std::string name2() { return "acmaes"; } +}; + +// fill fit data structure +ROOT::Fit::UnBinData * FillUnBinData(TTree * tree ) { + + // fill the unbin data set from a TTree + ROOT::Fit::UnBinData * d = 0; + + // for the large tree access directly the branches + d = new ROOT::Fit::UnBinData(); + + unsigned int n = tree->GetEntries(); +#ifdef DEBUG + std::cout << "number of unbin data is " << n << " of dim " << N << std::endl; +#endif + d->Initialize(n,N); + TBranch * bx = tree->GetBranch("x"); + double vx[N]; + bx->SetAddress(vx); + std::vector m(N); + for (int unsigned i = 0; i < n; ++i) { + bx->GetEntry(i); + d->Add(vx); + for (int j = 0; j < N; ++j) + m[j] += vx[j]; + } + +#ifdef DEBUG + std::cout << "average values of means :\n"; + for (int j = 0; j < N; ++j) + std::cout << m[j]/n << " "; + std::cout << "\n"; +#endif + + return d; +} + + +// unbin fit + +typedef ROOT::Math::IParamMultiFunction Func; +template +int DoUnBinFit(T * tree, Func & func, bool debug = false ) { + + ROOT::Fit::UnBinData * d = FillUnBinData(tree ); + // need to have done Tree->Draw() before fit + //FillUnBinData(d,tree); + + std::cout << "Filled the fit data " << std::endl; + //printData(d); + +#ifdef DEBUG + std::cout << "data size type and size is " << typeid(*d).name() << " " << d->Size() << std::endl; +#endif + + + + // create the fitter + //std::cout << "Fit parameter 2 " << f.Parameters()[2] << std::endl; + + ROOT::Fit::Fitter fitter; + fitter.Config().SetMinimizer(MinType::name().c_str(),MinType::name2().c_str()); + + if (debug) + fitter.Config().MinimizerOptions().SetPrintLevel(3); + else + fitter.Config().MinimizerOptions().SetPrintLevel(1); + + + // set tolerance 1 for tree to be same as in TTTreePlayer::UnBinFIt + fitter.Config().MinimizerOptions().SetTolerance(0.01); + + // set strategy (0 to avoid MnHesse + fitter.Config().MinimizerOptions().SetStrategy(strategy); + + + // create the function + + fitter.SetFunction(func); + // need to set limits to constant term + fitter.Config().ParSettings(0).SetLowerLimit(0.); + fitter.Config().ParSettings(1).SetLowerLimit(0.); + + if (debug) + std::cout << "do fitting... " << std::endl; + + bool ret = fitter.Fit(*d); + if (!ret) { + std::cout << " Fit Failed " << std::endl; + return -1; + } + if (debug) + fitter.Result().Print(std::cout); + + // check fit result + double chi2 = 0; + //if (fitter.Result().Value(0) < 0.5 ) { + for (int i = 0; i < NPar; ++i) { + double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) ); + chi2 += d*d; + } +//} +// else { +// double truePar2[NPar]; +// truePar2[0] = 1.-truePar[0]; +// truePar2[1] = truePar[3]; +// truePar2[2] = truePar[4]; +// truePar2[3] = truePar[1]; +// truePar2[4] = truePar[2]; +// for (int i = 0; i < N; ++i) { +// double d = ( truePar2[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) ); +// chi2 += d*d; +// } +// } + double prob = ROOT::Math::chisquared_cdf_c(chi2,NPar); + int iret = (prob < 1.0E-6) ? -1 : 0; + if (iret != 0) { + std::cout <<"Found difference in fitted values - chi2 = " << chi2 + << " prob = " << prob << std::endl; + fitter.Result().Print(std::cout); + } + + delete d; + + return iret; + +} + + +template +int DoFit(TTree * tree, Func & func, bool debug = false ) { + return DoUnBinFit(tree, func, debug); +} +// template +// int DoFit(TH1 * h1, Func & func, bool debug = false, bool copyData = false ) { +// return DoBinFit(h1, func, debug, copyData); +// } +// template +// int DoFit(TGraph * gr, Func & func, bool debug = false, bool copyData = false ) { +// return DoBinFit(gr, func, debug, copyData); +// } + +template +int FitUsingNewFitter(FitObj * fitobj, Func & func ) { + + std::cout << "\n************************************************************\n"; + std::cout << "\tFit using new Fit::Fitter " << typeid(*fitobj).name() << std::endl; + std::cout << "\tMinimizer is " << MinType::name() << " " << MinType::name2() << " func dim = " << func.NDim() << std::endl; + + int iret = 0; + TStopwatch w; w.Start(); + +#ifdef DEBUG + std::cout << "initial Parameters " << iniPar << " " << *iniPar << " " << *(iniPar+1) << std::endl; + func.SetParameters(iniPar); + iret |= DoFit(fitobj,func,true ); + if (iret != 0) { + std::cout << "Test failed " << std::endl; + } + +#else + for (int i = 0; i < nfit; ++i) { + func.SetParameters(iniPar); + iret = DoFit(fitobj,func, false); + if (iret != 0) { + std::cout << "Test failed " << std::endl; + break; + } + } +#endif + w.Stop(); + std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl; + std::cout << "\n************************************************************\n"; + + return iret; +} + + +int testNdimFit() { + + + std::cout << "\n\n************************************************************\n"; + std::cout << "\t UNBINNED TREE (GAUSSIAN MULTI-DIM) FIT\n"; + std::cout << "************************************************************\n"; + + TTree t1("t2","a large Tree with gaussian variables"); + double x[N]; + Int_t ev; + t1.Branch("x",x,branchType.c_str()); + t1.Branch("ev",&ev,"ev/I"); + + // generate the true parameters +// for (int j = 0; j < NGaus; ++j) { +// double a = j+1; +// double mu = double(j)/NGaus; +// double s = 1.0 + double(j)/NGaus; +// truePar[3*j] = a; +// truePar[3*j+1] = mu; +// truePar[3*j+2] = s; +// tot += a; +// } + truePar[0] = 0.2; // % second gaussian + truePar[1] = 0.05; // % third gaussian ampl + truePar[2] = 0.; // mean first gaussian + truePar[3] = 0.5; // s1 + truePar[4] = 0.; // mean secon gauss + truePar[5] = 1; + truePar[6] = -3; // mean third gaus + truePar[7] = 10; + + + + //fill the tree + TRandom3 r; + double norm = (1+truePar[0] + truePar[1] ); + double a = 1./norm; + double b = truePar[0]/ norm; + double c = truePar[1]/ norm; + assert(a+b+c == 1.); + std::cout << " True amplitude gaussians " << a << " " << b << " " << c << std::endl; + for (Int_t i=0;i f2(&gausSum,1,NPar,iniPar); + + int iret = 0; + iret |= FitUsingNewFitter(&t1,f2); + + return iret; +} + +int main() { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + return testNdimFit(); +} diff --git a/math/cmaes/test/testUserFunc.cxx b/math/cmaes/test/testUserFunc.cxx new file mode 100644 index 0000000000000..d175326201394 --- /dev/null +++ b/math/cmaes/test/testUserFunc.cxx @@ -0,0 +1,88 @@ +// @(#)root/minuit2:$Id$ +// Author: L. Moneta 10/2005 + +/********************************************************************** + * * + * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * + * * + **********************************************************************/ + + +#include "TApplication.h" +#include "TH1.h" +#include "TF1.h" +#include "TRandom3.h" +#include "Math/MinimizerOptions.h" +#include "TMath.h" +#include "TSystem.h" + +#include + +double myfunc( double * x, double * p) { + + return p[0]*TMath::Gaus(x[0],p[1],p[2]); +} + +void testUserFunc(std::string type="cmaes", int n = 1000) { + + + + gRandom = new TRandom3(); + + + ROOT::Math::MinimizerOptions::SetDefaultMinimizer(type.c_str() ); + + + + TH1D * h1 = new TH1D("h1","fit histo 1",100, -5, 5. ); + +// gStyle->SetOptStat(1111111); +// gStyle->SetOptFit(1111111); + + + + + for (int i = 0; i < n; ++i) { + h1->Fill( gRandom->Gaus(0,1) ); + } + + TF1 * f = new TF1("f",myfunc,-10,10,3); + double p[3] = { 100.0, 0.0, 1.0 } ; + f->SetParameters(p); + + h1->Fit(f); + // try fix a parameter + //TVirtualFitter * fitter = TVirtualFitter::GetFitter(); + //std::cout << typeid(*fitter).name() << std::endl; + //fitter->FixParameter(2); + f->FixParameter(2,1.0); + + h1->Fit(f,"V"); + + h1->Draw(); + + + +} + +#ifndef __CINT__ +int main(int argc, char **argv) +{ + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + if (argc > 1) { + TApplication theApp("App", &argc, argv); + testUserFunc( ); + theApp.Run(); + } + else + testUserFunc( ); + return 0; +} +#endif + +//#ifndef __CINT__ +//int main() { +// testUserFunc( ); +//} +//#endif diff --git a/math/mathcore/src/Factory.cxx b/math/mathcore/src/Factory.cxx index 03f02a29ac3e4..096a92c196636 100644 --- a/math/mathcore/src/Factory.cxx +++ b/math/mathcore/src/Factory.cxx @@ -26,6 +26,7 @@ // #define MATH_NO_PLUGIN_MANAGER // #define HAS_MINUIT // #define HAS_MINUIT2 +// #define HAS_CMAES #ifndef MATH_NO_PLUGIN_MANAGER // use ROOT Plug-in manager @@ -41,6 +42,9 @@ #ifdef HAS_MINUIT #include "TMinuitMinimizer.h" #endif +#ifdef HAS_CMAES +#include "TCMAESMinimizer.h" +#endif #ifdef R__HAS_MATHMORE #include "Math/GSLMinimizer.h" #include "Math/GSLNLSMinimizer.h" @@ -52,7 +56,6 @@ #include #include -//#define DEBUG #ifdef DEBUG #include #endif @@ -80,9 +83,14 @@ ROOT::Math::Minimizer * ROOT::Math::Factory::CreateMinimizer(const std::string & s1 = "Minuit"; minim = s1.c_str(); } - + if (minimizerType.find("cmaes")!=std::string::npos + ||minimizerType.find("ipop")!=std::string::npos) + { + s1 = minimizerType; + minim = s1.c_str(); + } if (minimizerType.empty() ) minim = ROOT::Math::MinimizerOptions::DefaultMinimizerType().c_str(); - + R__LOCKGUARD2(gROOTMutex); // create Minimizer using the PM @@ -104,8 +112,7 @@ ROOT::Math::Minimizer * ROOT::Math::Factory::CreateMinimizer(const std::string & else std::cout << "Error creating Minimizer " << minimizerType << " " << algoType << std::endl; #endif - - return min; + return min; } return 0; @@ -140,6 +147,12 @@ ROOT::Math::Minimizer * ROOT::Math::Factory::CreateMinimizer(const std::string & min = new TMinuitMinimizer(algoType.c_str()); #endif +#ifdef HAS_CMAES + if (minimizerType.find("cmaes") != std::string::npos + || minimizerType.find("ipop") != std::string::npos) + min = new ROOT::cmaes::TCMAESMinimizer(algoType.c_str()); +#endif + #ifdef R__HAS_MATHMORE // use GSL minimizer if (minimizerType == "GSL") diff --git a/math/mathcore/src/FitConfig.cxx b/math/mathcore/src/FitConfig.cxx index f2d7013eb3253..f29ddecfce912 100644 --- a/math/mathcore/src/FitConfig.cxx +++ b/math/mathcore/src/FitConfig.cxx @@ -158,8 +158,8 @@ void FitConfig::SetParamsSettings(unsigned int npar, const double *params, const if (val == 0) step = 0.3; } else - step = vstep[i]; - + step = vstep[i]; + if (createNew) fSettings.push_back( ParameterSettings("Par_" + ROOT::Math::Util::ToString(i), val, step ) ); else { diff --git a/math/mathcore/src/MinimizerOptions.cxx b/math/mathcore/src/MinimizerOptions.cxx index 1c8faffa09a57..e8512fad06477 100644 --- a/math/mathcore/src/MinimizerOptions.cxx +++ b/math/mathcore/src/MinimizerOptions.cxx @@ -162,11 +162,18 @@ void MinimizerOptions::ResetToDefaultOptions() { fMinimType = "Minuit2"; fAlgoType = "Fumili"; } + else if (fMinimType.find("cmaes")!=std::string::npos + || fMinimType.find("ipop")!=std::string::npos) + { + fAlgoType = fMinimType; + fMinimType = "cmaes"; + } else if (fMinimType == "GSLMultiMin" && fAlgoType == "Migrad") fAlgoType = "BFGS2"; delete fExtraOptions; fExtraOptions = 0; + // check if extra options exists (copy them if needed) if (Minim::gDefaultExtraOptions) fExtraOptions = Minim::gDefaultExtraOptions->Clone(); diff --git a/math/minuit2/src/Minuit2Minimizer.cxx b/math/minuit2/src/Minuit2Minimizer.cxx index 19e0b9098e4c0..0b6235ca77752 100644 --- a/math/minuit2/src/Minuit2Minimizer.cxx +++ b/math/minuit2/src/Minuit2Minimizer.cxx @@ -182,7 +182,7 @@ bool Minuit2Minimizer::SetVariable(unsigned int ivar, const std::string & name, // if index is wrong (i.e. variable already exists but with a different index return false) but // value is set for corresponding variable name -// std::cout << " add parameter " << name << " " << val << " step " << step << std::endl; + //std::cout << " add parameter " << name << " " << val << " step " << step << std::endl; if (step <= 0) { std::string txtmsg = "Parameter " + name + " has zero or invalid step size - consider it as constant "; diff --git a/tutorials/fit/Ifit.C b/tutorials/fit/Ifit.C index 48cd469e84f41..2f2767fff28c9 100644 --- a/tutorials/fit/Ifit.C +++ b/tutorials/fit/Ifit.C @@ -25,8 +25,8 @@ Double_t func(float x,float y,Double_t *par) //______________________________________________________________________________ void fcn(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag) { - const Int_t nbins = 5; - Int_t i; + const Int_t nbins = 5; + Int_t i; //calculate chisquare Double_t chisq = 0; diff --git a/tutorials/fit/cmaesFitBench.C b/tutorials/fit/cmaesFitBench.C new file mode 100644 index 0000000000000..3393b00bcc93d --- /dev/null +++ b/tutorials/fit/cmaesFitBench.C @@ -0,0 +1,139 @@ +//+ Fitting 1-D histograms with cmaes +// Author: L. Moneta 10/2005 +// Author: E. Benazera 05/2014 + +/********************************************************************** + * * + * Copyright (c) 2014 INRIA * + * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * + * * + **********************************************************************/ + +#include "TH1.h" +#include "TF1.h" +#include "TCanvas.h" +#include "TStopwatch.h" +#include "TSystem.h" +#include "TRandom3.h" +#include "TVirtualFitter.h" +#include "TPaveLabel.h" +#include "TStyle.h" +#include "TMath.h" +#include "TROOT.h" +#include "TFrame.h" +#include "TSystem.h" + +//#include "Fit/FitConfig.h" + + +TF1 *fitFcn; +TH1 *histo; + +bool libloaded = false; + +// Quadratic background function +Double_t background(Double_t *x, Double_t *par) { + return par[0] + par[1]*x[0] + par[2]*x[0]*x[0]; +} + +// Lorenzian Peak function +Double_t lorentzianPeak(Double_t *x, Double_t *par) { + return (0.5*par[0]*par[1]/TMath::Pi()) / + TMath::Max( 1.e-10,(x[0]-par[2])*(x[0]-par[2]) + .25*par[1]*par[1]); +} + +// Sum of background and peak function +Double_t fitFunction(Double_t *x, Double_t *par) { + return background(x,par) + lorentzianPeak(x,&par[3]); +} + +void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass, Double_t sigma, Int_t lambda) { + printf("\n*********************************************************************************\n"); + printf("\t %s \n",fitter); + printf("*********************************************************************************\n"); + + gRandom = new TRandom3(); + TStopwatch timer; + // timer.Start(); + TVirtualFitter::SetDefaultFitter(fitter); + //ROOT::Fit::FitConfig::SetDefaultMinimizer(fitter); + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); + opts.SetIntValue("lambda",lambda); + opts.SetIntValue("lscaling",1); + opts.SetRealValue("sigma",sigma); + + pad->SetGrid(); + pad->SetLogy(); + fitFcn->SetParameters(1,1,1,6,.03,1); + fitFcn->Update(); + std::string title = std::string(fitter) + " fit bench"; + histo = new TH1D(fitter,title.c_str(),200,0,3); + + timer.Start(); + for (Int_t pass=0;passSetParameters(1,1,1,6,.03,1); + for (Int_t i=0;i<5000;i++) { + histo->Fill(fitFcn->GetRandom()); + } + //histo->Print("all"); + //histo->Fit(fitFcn,"Q0"); // from TH1.cxx: Q: quiet, 0: do not plot + } + + histo->Fit(fitFcn,"V"); // E: use Minos, V: verbose. + timer.Stop(); + + (histo->GetFunction("fitFcn"))->SetLineColor(kRed+3); + gPad->SetFillColor(kYellow-10); + + + Double_t cputime = timer.CpuTime(); + printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter,npass,timer.RealTime(),cputime); + TPaveLabel *p = new TPaveLabel(0.45,0.7,0.88,0.8,Form("%s CPU= %g s",fitter,cputime),"brNDC"); + p->Draw(); + p->SetTextColor(kRed+3); + p->SetFillColor(kYellow-8); + pad->Update(); + + //delete p; + //delete histo; + delete gRandom; +} + +void cmaesFitBench(Int_t npass=20, Double_t sigma=0.1, Int_t lambda=-1) { + if (!libloaded) + { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + libloaded = true; + } + TH1::AddDirectory(kFALSE); + TCanvas *c1 = new TCanvas("FitBench","Fitting Demo",10,10,900,900); + c1->Divide(2,2); + c1->SetFillColor(kYellow-9); + // create a TF1 with the range from 0 to 3 and 6 parameters + fitFcn = new TF1("fitFcn",fitFunction,0,3,6); + fitFcn->SetNpx(200); + gStyle->SetOptFit(); + gStyle->SetStatY(0.6); + + //with Minuit2 + c1->cd(1); + DoFit("Minuit2",gPad,npass,sigma,lambda); + + //with Fumili + c1->cd(2); + DoFit("Fumili",gPad,npass,sigma,lambda); + + //with cmaes + c1->cd(3); + DoFit("cmaes",gPad,npass,sigma,lambda); + + //with acmaes + c1->cd(4); + DoFit("acmaes",gPad,npass,sigma,lambda); + + //c1->SaveAs("FitBench.root"); + //delete c1; + delete fitFcn; +} diff --git a/tutorials/fit/cmaesFitBench2D.C b/tutorials/fit/cmaesFitBench2D.C new file mode 100644 index 0000000000000..f84a0d163db52 --- /dev/null +++ b/tutorials/fit/cmaesFitBench2D.C @@ -0,0 +1,105 @@ +// Author: L. Moneta 10/2005 +// Author: E. Benazera 05/2014 + +/********************************************************************** + * * + * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * + * * + **********************************************************************/ + +#include "TH1.h" +#include "TF1.h" +#include "TH2D.h" +#include "TF2.h" +#include "TCanvas.h" +#include "TStopwatch.h" +#include "TSystem.h" +#include "TRandom3.h" +#include "TVirtualFitter.h" +#include "TPaveLabel.h" +#include "TStyle.h" + + +TF2 *fitFcn; +TH2D *histo; + +bool libloaded = false; + +// Quadratic background function +Double_t gaus2D(Double_t *x, Double_t *par) { + double t1 = x[0] - par[1]; + double t2 = x[1] - par[2]; + return par[0]* exp( - 0.5 * ( t1*t1/( par[3]*par[3]) + t2*t2 /( par[4]*par[4] ) ) ) ; +} + +// Sum of background and peak function +Double_t fitFunction(Double_t *x, Double_t *par) { + return gaus2D(x,par); +} + +void fillHisto(int n =10000) { + + gRandom = new TRandom3(); + for (int i = 0; i < n; ++i) { + double x = gRandom->Gaus(2,3); + double y = gRandom->Gaus(-1,4); + histo->Fill(x,y,1.); + } +} + +void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { + TStopwatch timer; + TVirtualFitter::SetDefaultFitter(fitter); + pad->SetGrid(); + fitFcn->SetParameters(100,0,0,2,7); + fitFcn->Update(); + + timer.Start(); + histo->Fit("fitFcn","0"); + timer.Stop(); + + histo->Draw(); + Double_t cputime = timer.CpuTime(); + printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter,npass,timer.RealTime(),cputime); + TPaveLabel *p = new TPaveLabel(0.5,0.7,0.85,0.8,Form("%s CPU= %g s",fitter,cputime),"brNDC"); + p->Draw(); + pad->Update(); +} + +void cmaesFitBench2D(int n = 100000) { + if (!libloaded) + { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + libloaded = true; + } + TH1::AddDirectory(kFALSE); + TCanvas *c1 = new TCanvas("c1","Fitting Demo",10,10,900,900); + c1->Divide(2,2); + // create a TF1 with the range from 0 to 3 and 6 parameters + fitFcn = new TF2("fitFcn",fitFunction,-10,10,-10,10,5); + //fitFcn->SetNpx(200); + gStyle->SetOptFit(); + gStyle->SetStatY(0.6); + + histo = new TH2D("h2","2D Gauss",100,-10,10,100,-10,10); + fillHisto(n); + + int npass=0; + + //with Minuit2 + c1->cd(3); + DoFit("Minuit2",gPad,npass); + + //with Fumili + c1->cd(4); + DoFit("Fumili",gPad,npass); + + //with cmaes + c1->cd(1); + DoFit("cmaes",gPad,npass); + + //with acmaes + c1->cd(2); + DoFit("acmaes",gPad,npass); +} diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C new file mode 100644 index 0000000000000..32b42762fb2f7 --- /dev/null +++ b/tutorials/fit/cmaesFullBench.C @@ -0,0 +1,1037 @@ +// Author: E. Benazera 6/2014 + +#include +#include +#include +#include + +#include "TH1.h" +#include "TF1.h" +#include "TH2D.h" +#include "TF2.h" +#include "TStopwatch.h" +#include "TRandom3.h" +#include "TVirtualFitter.h" +#include "TPaveLabel.h" +#include "TStyle.h" +#include "TSystem.h" +#include "TFile.h" +#include "TList.h" +#include "TMath.h" +#include "TROOT.h" + +class expstats +{ +public: + expstats(const std::string &name, + const int &dim, + const int &lambda=-1): + _name(name),_dim(dim),_lambda(lambda) {} + ~expstats() {} + + void add_exp(const bool &succ, + const double &fmin, + const std::vector &x, + const double &cputime, + const double &budget) + { + if (succ) + ++_succs; + else ++_fails; + _vsuccs.push_back(succ); + _fmin.push_back(fmin); + _x.push_back(x); + _cputime.push_back(cputime); + _cpu_avg = std::accumulate(_cputime.begin(),_cputime.end(),0.0) / static_cast(_cputime.size()); + _cpu_std = stddev(_cputime,_cpu_avg); + _budget.push_back(budget); + _budget_avg = std::accumulate(_budget.begin(),_budget.end(),0.0) / static_cast(_budget.size()); + _budget_std = stddev(_budget,_budget_avg); + } + + void merge(const expstats &stats) + { + for (size_t i=0;i _vsuccs; + std::vector _fmin; + std::vector> _x; + std::vector _cputime; + double _cpu_avg = 0.0; + double _cpu_std = 0.0; + std::vector _budget; + double _budget_avg = 0.0; + double _budget_std = 0.0; + + int _lambda = -1; + + // diff + int _found = 0; /* number of times the correct minima was found. */ + std::vector _fdiff; + std::vector _cputime_diff; + std::vector _cputime_ratio; + std::vector _budget_diff; + std::vector _budget_ratio; + double _cputime_diff_avg = 0.0; + double _cputime_ratio_avg = 1.0; + double _budget_diff_avg = 0.0; + double _budget_ratio_avg = 1.0; + int _isuccs = 0; /* number of times the best f-min among the two algorithms, was found. */ + int _ifails = 0; + int _iequals = 0; /* number of times the same fmin was found. */ +}; + +std::ostream& operator<<(std::ostream &out, const expstats &stats) +{ + return stats.print(out); +} + +typedef std::function ExpFunc; + +class experiment +{ +public: + experiment(const std::string &name) + :_name(name) + { + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetRealValue("sigma",0.1); + } + + void set_lambda(const int &lambda) + { + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetIntValue("lambda",lambda); + _lambda = lambda; + } + + void set_lscaling(const int &lscaling) + { + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetIntValue("lscaling",lscaling); + } + + void set_restarts(const int &nrestarts) + { + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default("cmaes"); + opts.SetIntValue("restarts",nrestarts); + } + + virtual ~experiment() {} + + virtual void Setup() {} + + virtual void Cleanup() {} + + ExpFunc _ef; + std::string _name; + int _lambda = -1; +}; + +/*- gauss_fit -*/ +class gauss_fit_e : public experiment +{ +public: + gauss_fit_e() + :experiment("gauss_fit") + { + _ef = [this](const std::string &fitter) + { + std::string ename = "gauss_fit"; + + TVirtualFitter::SetDefaultFitter(fitter.c_str() ); + TH1D * h1 = new TH1D("h1f1","Chi2 Fit",100, -5, 5. ); + TH1D * h1bis = new TH1D("h1f2","Likelihood Fit",100, -5, 5. ); + for (int i = 0; i < _n; ++i) { + h1->Fill( _x.at(i) ); + h1bis->Fill( _x.at(i) ); + } + delete ((TF1 *)(gROOT->GetFunction("gaus"))); + TStopwatch timer; + timer.Start(); + TFitResultPtr r1 = h1->Fit("gaus","VS0"); + timer.Stop(); + Double_t cputime1 = timer.CpuTime(); + delete ((TF1 *)(gROOT->GetFunction("gaus"))); + TStopwatch timer2; + timer2.Start(); + TFitResultPtr r2 = h1bis->Fit("gaus","VLS0"); + timer2.Stop(); + Double_t cputime2 = timer2.CpuTime(); + + delete h1; + delete h1bis; + + expstats stats(ename,r1->NTotalParameters(),_lambda); + stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); + stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); + std::cout << "gaus_fit stats: " << stats << std::endl; + std::cout << "fmin1=" << r1->MinFcnValue() << std::endl;//" / fmin2=" << r2->MinFcnValue() << std::endl; + return stats; + }; + } + + ~gauss_fit_e() {} + + virtual void Setup() + { + std::cout << "setting up gauss_fit\n"; + for (int i=0;i<_n;i++) + _x.push_back(_grandom.Gaus(0,1)); + } + + int _n = 1000; + TRandom3 _grandom; + std::vector _x; +}; +gauss_fit_e ggauss_fit; + +/*- lorentz_fit -*/ +class lorentz_fit_e : public experiment +{ +public: + lorentz_fit_e() + :experiment("lorentz_fit") + { + _ef = [this](const std::string &fitter) + { + std::string title = "fit bench"; + std::string ename = "lorentz_fit"; + expstats stats(ename,6,_lambda); + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + + TH1D *mhisto =new TH1D("fit",title.c_str(),200,0,3); + for (Int_t pass=0;pass<_npass;pass++) { + TStopwatch timer; + TF1 *fitFcn = new TF1("fitFcn",lorentz_fit_e::fitFunction,0,3,6); + fitFcn->SetParameters(1,1,1,6,.03,1); + TH1D *histo = new TH1D("fit2",title.c_str(),200,0,3); + //histo->Print("all"); + for (Int_t j=0;j<5000;j++) + { + histo->Fill(_xs.at(pass).at(j)); + mhisto->Fill(_xs.at(pass).at(j)); + } + /*timer.Start(); + TFitResultPtr r = histo->Fit(fitFcn,"VS0"); // from TH1.cxx: Q: quiet, 0: do not plot + timer.Stop(); + Double_t cputime = timer.CpuTime(); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls());*/ + delete histo; + delete fitFcn; + } + TStopwatch timer; + timer.Start(); + TF1 *fitFcn = new TF1("fitFcn",lorentz_fit_e::fitFunction,0,3,6); + fitFcn->SetParameters(1,1,1,6,.03,1); + TFitResultPtr r = mhisto->Fit(fitFcn,"VS0"); + timer.Stop(); + double cputime = timer.CpuTime(); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + printf("%s, npass=%d : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),_npass,timer.RealTime(),cputime); + //std::cout << "lorentz_fit stats: " << stats << std::endl; + delete mhisto; + delete fitFcn; + return stats; + }; + } + + virtual ~lorentz_fit_e() + { + _xs.clear(); + } + + // Quadratic background function + static Double_t background(Double_t *x, Double_t *par) { + return par[0] + par[1]*x[0] + par[2]*x[0]*x[0]; + } + + // Lorenzian Peak function + static Double_t lorentzianPeak(Double_t *x, Double_t *par) { + return (0.5*par[0]*par[1]/TMath::Pi()) / + TMath::Max( 1.e-10,(x[0]-par[2])*(x[0]-par[2]) + .25*par[1]*par[1]); + } + + // Sum of background and peak function + static Double_t fitFunction(Double_t *x, Double_t *par) { + return lorentz_fit_e::background(x,par) + lorentz_fit_e::lorentzianPeak(x,&par[3]); + } + + virtual void Setup() + { + TF1 *fitFcn = new TF1("fitFcn",lorentz_fit_e::fitFunction,0,3,6); + fitFcn->SetNpx(200); + fitFcn->SetParameters(1,1,1,6,.03,1); + fitFcn->Update(); + std::vector x; + for (int i=0;i<_npass;i++) + { + for (Int_t j=0;j<5000;j++) { + x.push_back(fitFcn->GetRandom()); + } + _xs.push_back(x); + } + delete fitFcn; + } + + virtual void Cleanup() + { + _xs.clear(); + } + + int _npass = 20; + //TF1 *_fitFcn; + std::vector > _xs; +}; +lorentz_fit_e glorentz_fit; + +/*- gauss2D_fit -*/ +class gauss2D_fit_e : public experiment +{ +public: + gauss2D_fit_e() + :experiment("gauss2D_fit") + { + _ef = [this](const std::string &fitter) + { + std::string ename = "gauss2D_fit"; + int npass = 0; + int n = 100000; + TStopwatch timer; + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + TF2 *fitFcn = new TF2("fitFcn",gauss2D_fit_e::fitFunction2,-10,10,-10,10,5); + fitFcn->SetParameters(100,0,0,2,7); + fitFcn->Update(); + timer.Start(); + TFitResultPtr r = _histo->Fit("fitFcn","VS0"); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + printf("%s : RT=%7.3f s, Cpu=%7.3f s\n",fitter.c_str(),timer.RealTime(),cputime); + delete fitFcn; + expstats stats(ename,r->NTotalParameters(),_lambda); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + std::cout << "gauss2D_fit stats: " << stats << std::endl; + return stats; + }; + } + + ~gauss2D_fit_e() + { + if (_histo) + delete _histo; + } + + // Quadratic background function + static Double_t gaus2D(Double_t *x, Double_t *par) { + double t1 = x[0] - par[1]; + double t2 = x[1] - par[2]; + return par[0]* exp( - 0.5 * ( t1*t1/( par[3]*par[3]) + t2*t2 /( par[4]*par[4] ) ) ) ; + } + + // Sum of background and peak function + static Double_t fitFunction2(Double_t *x, Double_t *par) { + return gaus2D(x,par); + } + + static void fillHisto(int n, + TH2D *histo) + { + gRandom = new TRandom3(); + for (int i = 0; i < n; ++i) { + double x = gRandom->Gaus(2,3); + double y = gRandom->Gaus(-1,4); + histo->Fill(x,y,1.); + } + } + + virtual void Setup() + { + _histo = new TH2D("h2","2D Gauss",100,-10,10,100,-10,10); + fillHisto(_n,_histo); + } + + virtual void Cleanup() + { + if (_histo) + delete _histo; + _histo = nullptr; + } + + int _n = 100000; + TH2D *_histo = nullptr; +}; +gauss2D_fit_e ggauss2D_fit; + +/*- fit2a -*/ +class fit2a_e : public experiment +{ +public: + fit2a_e() + :experiment("fit2a") + { + _ef = [this](const std::string &fitter) + { + const Int_t npar = 15; + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + TF2 *f2 = new TF2("f2",fun2,-10,10,-10,10, npar); + TH2F *h2 = new TH2F("h2","From f2",40,-10,10,40,-10,10); + for (int i=0;i<_nentries;i++) + h2->Fill(_x.at(i),_y.at(i)); + + Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + Float_t ratio = 4*_nentries/100000; + f2params[ 0] *= ratio; + f2params[ 5] *= ratio; + f2params[10] *= ratio; + f2->SetParameters(f2params); + + //Fit h2 with original function f2 + TStopwatch timer; + timer.Start(); + TFitResultPtr r = h2->Fit("f2","SN0"); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + expstats stats("fit2a",r->NTotalParameters(),_lambda); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + delete h2; + delete f2; + return stats; + }; + } + + ~fit2a_e() + { + Cleanup(); + } + + static Double_t g2(Double_t *x, Double_t *par) { + Double_t r1 = Double_t((x[0]-par[1])/par[2]); + Double_t r2 = Double_t((x[1]-par[3])/par[4]); + return par[0]*TMath::Exp(-0.5*(r1*r1+r2*r2)); + } + + static Double_t fun2(Double_t *x, Double_t *par) { + Double_t *p1 = &par[0]; + Double_t *p2 = &par[5]; + Double_t *p3 = &par[10]; + Double_t result = g2(x,p1) + g2(x,p2) + g2(x,p3); + return result; + } + + virtual void Setup() + { + const Int_t npar = 15; + Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + TF2 *f2 = new TF2("f2",fun2,-10,10,-10,10, npar); + f2->SetParameters(f2params); + _x = std::vector(_nentries); + _y = std::vector(_nentries); + for (int i=0;i<_nentries;i++) + f2->GetRandom2(_x.at(i),_y.at(i)); + delete f2; + } + + virtual void Cleanup() + { + } + + int _nentries = 100000; + std::vector _x,_y; +}; +fit2a_e gfit2a; + +/*- fit2dhist -*/ +class fit2dhist_e : public experiment +{ +public: + fit2dhist_e() + :experiment("fit2dhist") + { + _ef = [this](const std::string &fitter) + { + int nbx1 = 50; + int nby1 = 50; + int nbx2 = 50; + int nby2 = 50; + double xlow1 = 0.; + double ylow1 = 0.; + double xup1 = 10.; + double yup1 = 10.; + double xlow2 = 5.; + double ylow2 = 5.; + double xup2 = 20.; + double yup2 = 20.; + TH2D *h1 = new TH2D("h1","core",nbx1,xlow1,xup1,nby1,ylow1,yup1); + TH2D *h2 = new TH2D("h2","tails",nbx2,xlow2,xup2,nby2,ylow2,yup2); + double iniParams[10] = { 100, 6., 2., 7., 3, 100, 12., 3., 11., 2. }; + TF2 *func1 = new TF2("func",fit2dhist_e::my2Dfunc,xlow2,xup2,ylow2,yup2, 10); + func1->SetParameters(iniParams); + TF2 *func2 = new TF2("func",fit2dhist_e::my2Dfunc,xlow2,xup2,ylow2,yup2, 10); + func2->SetParameters(iniParams); + + // fill up histograms. + int n1 = 1000000; + int n2 = 1000000; + for (int i=0;iFill(_xr1.at(i),_yr1.at(i)); + h2->Fill(_xr2.at(i),_yr2.at(i)); // since n1 == n2. + } + + // scale histograms to same heights (for fitting) + double dx1 = (xup1-xlow1)/double(nbx1); + double dy1 = (yup1-ylow1)/double(nby1); + double dx2 = (xup2-xlow2)/double(nbx2); + double dy2 = (yup2-ylow2)/double(nby2); + // scale histo 2 to scale of 1 + h2->Sumw2(); + h2->Scale( ( double(n1) * dx1 * dy1 ) / ( double(n2) * dx2 * dy2 ) ); + + TStopwatch timer; + timer.Start(); + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + TFitResultPtr r1 = h1->Fit(func1,"VS0"); + timer.Stop(); + Double_t cputime1 = timer.CpuTime(); + TStopwatch timer2; + timer2.Start(); + TFitResultPtr r2 = h2->Fit(func2,"VS0"); + timer2.Stop(); + Double_t cputime2 = timer2.CpuTime(); + expstats stats("fit2dhist",r1->NTotalParameters(),_lambda); + stats.add_exp(r1->Status()==0,r1->MinFcnValue(),r1->Parameters(),cputime1,r1->NCalls()); + stats.add_exp(r2->Status()==0,r2->MinFcnValue(),r2->Parameters(),cputime2,r2->NCalls()); + delete h1; + delete h2; + delete func1; + delete func2; + return stats; + }; + } + + ~fit2dhist_e() + { + Cleanup(); + } + + static double gauss2D(double *x, double *par) { + double z1 = double((x[0]-par[1])/par[2]); + double z2 = double((x[1]-par[3])/par[4]); + return par[0]*exp(-0.5*(z1*z1+z2*z2)); + } + + static double my2Dfunc(double *x, double *par) { + return gauss2D(x,&par[0]) + gauss2D(x,&par[5]); + } + + static void FillHisto2(std::vector &xr, std::vector &yr, int n, double * p) + { + const double mx1 = p[1]; + const double my1 = p[3]; + const double sx1 = p[2]; + const double sy1 = p[4]; + const double mx2 = p[6]; + const double my2 = p[8]; + const double sx2 = p[7]; + const double sy2 = p[9]; + //const double w1 = p[0]*sx1*sy1/(p[5]*sx2*sy2); + const double w1 = 0.5; + + double x, y; + for (int i = 0; i < n; ++i) { + // generate randoms with larger gaussians + fit2dhist_e::_rndm.Rannor(x,y); + + double r = fit2dhist_e::_rndm.Rndm(1); + if (r < w1) { + x = x*sx1 + mx1; + y = y*sy1 + my1; + } + else { + x = x*sx2 + mx2; + y = y*sy2 + my2; + } + xr.push_back(x); + yr.push_back(y); + } + } + + void Setup() + { + double xlow1 = 0.; + double ylow1 = 0.; + double xup1 = 10.; + double yup1 = 10.; + double xlow2 = 5.; + double ylow2 = 5.; + double xup2 = 20.; + double yup2 = 20.; + double iniParams[10] = { 100, 6., 2., 7., 3, 100, 12., 3., 11., 2. }; + int n1 = 1000000; + int n2 = 1000000; + FillHisto2(_xr1,_yr1,n1,iniParams); + FillHisto2(_xr2,_yr2,n2,iniParams); + } + + void Cleanup() + { + } + + static TRandom3 _rndm; + std::vector _xr1,_yr1,_xr2,_yr2; +}; +TRandom3 fit2dhist_e::_rndm = TRandom3(); +fit2dhist_e gfit2dhist; + +/*- combined_fit -*/ +class combined_fit_e : public experiment +{ +public: + struct GlobalChi2 { + GlobalChi2( ROOT::Math::IMultiGenFunction & f1, + ROOT::Math::IMultiGenFunction & f2) : + fChi2_1(&f1), fChi2_2(&f2) {} + + // parameter vector is first background (in common 1 and 2) + // and then is signal (only in 2) + double operator() (const double *par) const { + int iparB[2] = {0,2}; + int iparSB[5] = {1,2,3,4,5}; + double p1[2]; + for (int i = 0; i < 2; ++i) p1[i] = par[iparB[i] ]; + + double p2[5]; + for (int i = 0; i < 5; ++i) p2[i] = par[iparSB[i] ]; + + return (*fChi2_1)(p1) + (*fChi2_2)(p2); + } + + const ROOT::Math::IMultiGenFunction * fChi2_1; + const ROOT::Math::IMultiGenFunction * fChi2_2; + }; + + combined_fit_e() + :experiment("combined_fit") + { + _ef = [this](const std::string &fitter) + { + // perform now global fit + TF1 * fSB = new TF1("fSB","expo + gaus(2)",0,100); + + ROOT::Math::WrappedMultiTF1 wfB(*_fB,1); + ROOT::Math::WrappedMultiTF1 wfSB(*fSB,1); + + ROOT::Fit::DataOptions opt; + ROOT::Fit::DataRange rangeB; + // set the data range + rangeB.SetRange(10,90); + ROOT::Fit::BinData dataB(opt,rangeB); + ROOT::Fit::FillData(dataB, _hB); + + ROOT::Fit::DataRange rangeSB; + rangeSB.SetRange(10,50); + ROOT::Fit::BinData dataSB(opt,rangeSB); + ROOT::Fit::FillData(dataSB, _hSB); + + ROOT::Fit::Chi2Function chi2_B(dataB, wfB); + ROOT::Fit::Chi2Function chi2_SB(dataSB, wfSB); + + GlobalChi2 globalChi2(chi2_B, chi2_SB); + + ROOT::Fit::Fitter rfitter; + + const int Npar = 6; + double par0[Npar] = { 5,5,-0.1,100, 30,10}; + + // create before the parameter settings in order to fix or set range on them + rfitter.Config().SetParamsSettings(6,par0); + // fix 5-th parameter + //rfitter.Config().ParSettings(4).Fix(); // weird random crash, not yet understood: fitter tries to set variable 4 instead of 5, sometimes... + // set limits on the third and 4-th parameter + rfitter.Config().ParSettings(2).SetLimits(-10,-1.E-4); + rfitter.Config().ParSettings(3).SetLimits(0,10000); + rfitter.Config().ParSettings(3).SetStepSize(5); + + rfitter.Config().MinimizerOptions().SetPrintLevel(0); + if (fitter == "Minuit2") + rfitter.Config().SetMinimizer("Minuit2","Migrad"); + else rfitter.Config().SetMinimizer("cmaes",fitter.c_str()); + + // fit FCN function directly + // (specify optionally data size and flag to indicate that is a chi2 fit) + TStopwatch timer; + timer.Start(); + std::cout << "starting\n"; + rfitter.FitFCN(6,globalChi2,0,dataB.Size()+dataSB.Size(),true); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + ROOT::Fit::FitResult r = rfitter.Result(); + //result.Print(std::cout); + + delete fSB; + expstats stats("combined",r.NTotalParameters(),_lambda); + stats.add_exp(r.Status()==0,r.MinFcnValue(),r.Parameters(),cputime,r.NCalls()); + std::cout << "combined stats: " << stats << std::endl; + std::cout << "fmin=" << r.MinFcnValue() << std::endl; + return stats; + }; + } + + ~combined_fit_e() + { + Cleanup(); + } + + virtual void Setup() + { + _hB = new TH1D("hB","histo B",100,0,100); + _hSB = new TH1D("hSB","histo S+B",100, 0,100); + _fB = new TF1("fB","expo",0,100); + _fB->SetParameters(1,-0.05); + _hB->FillRandom("fB"); + _fS = new TF1("fS","gaus",0,100); + _fS->SetParameters(1,30,5); + _hSB->FillRandom("fB",2000); + _hSB->FillRandom("fS",1000); + } + + virtual void Cleanup() + { + if (_hB) + delete _hB; + if (_hSB) + delete _hSB; + if (_fB) + delete _fB; + if (_fS) + delete _fS; + } + + TH1D *_hB = nullptr; + TH1D *_hSB = nullptr; + TF1 *_fB = nullptr; + TF1 *_fS = nullptr; +}; +combined_fit_e gcombined_fit; + +/*- ex3d -*/ +class ex3d_e : public experiment +{ +public: + ex3d_e() + :experiment("ex3d") + { + _ef = [this](const std::string &fitter) + { + double ev = 0.1; + + // create a 3d binned data structure + ROOT::Fit::BinData data(_n,3); + double xx[3]; + for(int i = 0; i < _n; ++i) { + xx[0] = _x[i]; + xx[1] = _y[i]; + xx[2] = _z[i]; + // add the 3d-data coordinate, the predictor value (v[i]) and its errors + data.Add(xx, _v[i], ev); + } + + TF3 * f3 = new TF3("f3","[0] * sin(x) + [1] * cos(y) + [2] * z",0,10,0,10,0,10); + f3->SetParameters(2,2,2); + ROOT::Fit::Fitter rfitter; + /*if (fitter.find("cmaes")!=std::string::npos) + rfitter.Config().SetMinimizer("cmaes","acmaes");*/ + if (fitter != "Minuit2") + rfitter.Config().SetMinimizer("cmaes",fitter.c_str()); + // wrapped the TF1 in a IParamMultiFunction interface for the Fitter class + ROOT::Math::WrappedMultiTF1 wf(*f3,3); + rfitter.SetFunction(wf); + TStopwatch timer; + timer.Start(); + bool ret = rfitter.Fit(data); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + const ROOT::Fit::FitResult & res = rfitter.Result(); + if (ret) { + // print result (should be around 1) + res.Print(std::cout); + // copy all fit result info (values, chi2, etc..) in TF3 + f3->SetFitResult(res); + // test fit p-value (chi2 probability) + double prob = res.Prob(); + if (prob < 1.E-2) + Error("exampleFit3D","Bad data fit - fit p-value is %f",prob); + else + std::cout << "Good fit : p-value = " << prob << std::endl; + } + else Error("exampleFit3D","3D fit failed"); + expstats stats("example3D",res.NTotalParameters(),_lambda); + stats.add_exp(res.Status()==0,res.MinFcnValue(),res.Parameters(),cputime,res.NCalls()); + delete f3; + return stats; + }; + } + + ~ex3d_e() + { + } + + virtual void Setup() + { + double ev = 0.1; + TRandom2 r; + for (int i = 0; i < _n; ++i) { + _x.push_back(r.Uniform(0,10)); + _y.push_back(r.Uniform(0,10)); + _z.push_back(r.Uniform(0,10)); + _v.push_back(sin(_x[i] ) + cos(_y[i]) + _z[i] + r.Gaus(0,ev)); + } + } + + virtual void Cleanup() + { + _x.clear(); + _y.clear(); + _z.clear(); + _v.clear(); + } + + int _n = 1000; + std::vector _x; + std::vector _y; + std::vector _z; + std::vector _v; +}; +ex3d_e gex3d; + +/*- fit2 -*/ +class fit2_e : public experiment +{ +public: + fit2_e() + :experiment("fit2") + { + _ef = [this](const std::string &fitter) + { + TVirtualFitter::SetDefaultFitter(fitter.c_str()); + TF2 *f2 = new TF2("f2",fit2_e::fun22,-10,10,-10,10, _npar); + + Double_t f2params[15] = + {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + Float_t ratio = 4*_nentries/100000; + f2params[ 0] *= ratio; + f2params[ 5] *= ratio; + f2params[10] *= ratio; + f2->SetParameters(f2params); + + TH2F *h2 = new TH2F("h2","from f2",40,-10,10,40,-10,10); + for (int i=0;i<_nentries;i++) + h2->Fill(_x.at(i),_y.at(i)); + + //Fit h2 with original function f2 + TStopwatch timer; + timer.Start(); + TFitResultPtr r = h2->Fit("f2","VS0"); + timer.Stop(); + Double_t cputime = timer.CpuTime(); + expstats stats("fit2",r->NTotalParameters(),_lambda); + stats.add_exp(r->Status()==0,r->MinFcnValue(),r->Parameters(),cputime,r->NCalls()); + delete h2; + delete f2; + return stats; + }; + } + + ~fit2_e() + { + } + + virtual void Setup() + { + TF2 *f2 = new TF2("f2",fit2_e::fun22,-10,10,-10,10, _npar); + Double_t f2params[15] = + {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + f2->SetParameters(f2params); + _x = std::vector(_nentries); + _y = std::vector(_nentries); + for (int i=0;i<_nentries;i++) + f2->GetRandom2(_x.at(i),_y.at(i)); + delete f2; + } + + static Double_t g22(Double_t *x, Double_t *par) { + Double_t r1 = Double_t((x[0]-par[1])/par[2]); + Double_t r2 = Double_t((x[1]-par[3])/par[4]); + return par[0]*TMath::Exp(-0.5*(r1*r1+r2*r2)); + } + + static Double_t fun22(Double_t *x, Double_t *par) { + Double_t *p1 = &par[0]; + Double_t *p2 = &par[5]; + Double_t *p3 = &par[10]; + Double_t result = fit2_e::g22(x,p1) + fit2_e::g22(x,p2) + fit2_e::g22(x,p3); + return result; + } + + Int_t _nentries = 100000; + Int_t _npar = 15; + std::vector _x, _y; +}; +fit2_e gfit2; + +void cmaesFullBench(const int &n=100, + const int &lscaling=1) +{ + std::cout << "Proceeding with " << n << " runs on every problems\n"; + if (lscaling > 0) + std::cout << "Linear scaling of parameters in ON\n"; + //std::vector lambdas = {-1, 5, 10, 20, 40, 80, 160, 320, 640, 1280}; + std::vector lambdas = {-1, 50, 200, -2, -3}; + std::vector acmaes_stats; + std::vector minuit2_stats; + std::map mexperiments; + //mexperiments.insert(std::pair(ggauss_fit._name,&ggauss_fit)); + mexperiments.insert(std::pair(glorentz_fit._name,&glorentz_fit)); + /*mexperiments.insert(std::pair(gfit2._name,&gfit2)); + mexperiments.insert(std::pair(ggauss2D_fit._name,&ggauss2D_fit)); + mexperiments.insert(std::pair(gfit2a._name,&gfit2a)); + mexperiments.insert(std::pair(gfit2dhist._name,&gfit2dhist)); + mexperiments.insert(std::pair(gcombined_fit._name,&gcombined_fit)); + mexperiments.insert(std::pair(gex3d._name,&gex3d));*/ + int nexp = mexperiments.size(); + int cn = 0; + std::map::iterator mit = mexperiments.begin(); + while(mit!=mexperiments.end()) + { + std::cout << "Running " << (*mit).first << std::endl; + for (int i=0;iSetup(); + for (int j=0;j<(int)lambdas.size();j++) + { + std::string fitter_name = "acmaes"; + if (lambdas.at(j) >= -1) + (*mit).second->set_lambda(lambdas.at(j)); + else if (lambdas.at(j) == -2) + { + (*mit).second->set_lambda(-1); + (*mit).second->set_restarts(4); + fitter_name = "aipop"; + } + else if (lambdas.at(j) == -3) + { + (*mit).second->set_lambda(-1); + (*mit).second->set_restarts(10); + fitter_name = "abipop"; + } + (*mit).second->set_lscaling(lscaling); + + if (i == 0) + { + acmaes_stats.push_back((*mit).second->_ef(fitter_name)); + } + else + { + acmaes_stats.at(cn*(lambdas.size())+j).merge((*mit).second->_ef(fitter_name)); + } + } + (*mit).second->set_lambda(-1); // N/A to Minuit2 + if (i == 0) + minuit2_stats.push_back((*mit).second->_ef("Minuit2")); + else minuit2_stats.back().merge((*mit).second->_ef("Minuit2")); + (*mit).second->Cleanup(); + } + ++cn; + ++mit; + } + + std::cout << "nexp=" << nexp << " / stats size=" << acmaes_stats.size() << std::endl; + + for (size_t i=0;i +#include + +bool libloaded = false; + +void testGausFit( std::string type = "cmaes", int n = 1000) { + + gRandom = new TRandom3(); + + TVirtualFitter::SetDefaultFitter(type.c_str() ); + + std::string name; + name = "h1_" + type; + TH1D * h1 = new TH1D(name.c_str(),"Chi2 Fit",100, -5, 5. ); + name = "h1bis_" + type; + TH1D * h1bis = new TH1D(name.c_str(),"Likelihood Fit",100, -5, 5. ); + /*name = "h2_" + type; + TH1D * h2 = new TH1D(name.c_str(),"Chi2 Fit with Minos Error",100, -5, 5. ); + name = "h3_" + type; + TH1D * h3 = new TH1D(name.c_str(),"Chi2 Fit with Integral and Minos",100, -5, 5. ); + name = "h4_" + type; + TH1D * h4 = new TH1D(name.c_str(),"Likelihood Fit with Minos Error",100, -5, 5. );*/ + + gStyle->SetOptStat(1111111); + gStyle->SetOptFit(1111111); + + for (int i = 0; i < n; ++i) { + double x = gRandom->Gaus(0,1); + h1->Fill( x ); + h1bis->Fill( x ); + /* h2->Fill( x ); + h3->Fill( x ); + h4->Fill( x ); */ + } + + std::string cname = type + "Canvas" ; + std::string ctitle = type + " Gaussian Fit" ; + TCanvas *c1 = new TCanvas(cname.c_str(),cname.c_str(),10,10,900,900); + c1->Divide(2,1); + + c1->cd(1); + cout << "\nDo Fit 1\n"; + h1->Fit("gaus","Q"); + h1->Draw(); + c1->cd(2); + cout << "\nDo Fit 1bis\n"; + h1bis->Fit("gaus","VLE"); + h1bis->Draw(); + /*c1->cd(2); + cout << "\nDo Fit 2\n"; + h2->Fit("gaus","VE"); + h2->Draw(); + c1->cd(3); + cout << "\nDo Fit 3\n"; + h3->Fit("gaus","IE"); + h3->Draw(); + c1->cd(4); + cout << "\nDo Fit 4\n"; + h4->Fit("gaus","VLE"); + h4->Draw();*/ + +} + +void cmaesGausFit() { + if (!libloaded) + { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + libloaded = true; + } + int n = 1000; + testGausFit("cmaes",n); + //testGausFit("acmaes",n); +} + + + diff --git a/tutorials/fit/cmaes_fit2a.C b/tutorials/fit/cmaes_fit2a.C new file mode 100644 index 0000000000000..612893be4843e --- /dev/null +++ b/tutorials/fit/cmaes_fit2a.C @@ -0,0 +1,85 @@ +#include "TF2.h" +#include "TH2.h" +#include "TCutG.h" +#include "TMath.h" +#include "TCanvas.h" +#include "TStyle.h" +#include "TVirtualFitter.h" + + +//+ Fitting a 2-D histogram (a variant) +// This tutorial illustrates : +// - how to create a 2-d function +// - fill a 2-d histogram randomly from this function +// - fit the histogram +// - display the fitted function on top of the histogram (lego-plot) +// using a surface plot in a sub-range of the histogram. +// +// This example can be executed via the interpreter or/and the compiler +// root > .x fit2a.C +// root > .x fit2a.C++ +//Author: Rene Brun +//Author: Emmanuel Benazera + +bool libloaded = false; + +Double_t g2(Double_t *x, Double_t *par) { + Double_t r1 = Double_t((x[0]-par[1])/par[2]); + Double_t r2 = Double_t((x[1]-par[3])/par[4]); + return par[0]*TMath::Exp(-0.5*(r1*r1+r2*r2)); +} +Double_t fun2(Double_t *x, Double_t *par) { + Double_t *p1 = &par[0]; + Double_t *p2 = &par[5]; + Double_t *p3 = &par[10]; + Double_t result = g2(x,p1) + g2(x,p2) + g2(x,p3); + return result; +} + +TCanvas *fit2a(const char *fitter="cmaes") { + if (!libloaded) + { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + libloaded = true; + } + + TVirtualFitter::SetDefaultFitter(fitter); + + ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); + //ROOT::Math::IOptions *opts = ROOT::Math::MinimizerOptions::FindDefault(fitter); + //opts.SetIntValue("lambda",100); + opts.SetNamedValue("fplot","fit2a.dat"); + + TCanvas *c = new TCanvas(); + gStyle->SetOptStat(kTRUE); + gStyle->SetPalette(1); + const Int_t npar = 15; + Double_t f2params[npar] = {100,-3,3,-3,3,160,0,0.8,0,0.9,40,4,0.7,4,0.7}; + TF2 *f2 = new TF2("f2",fun2,-10,10,-10,10, npar); + f2->SetParameters(f2params); + + //Create an histogram and fill it randomly with f2 + TH2F *h2 = new TH2F("h2","From f2",40,-10,10,40,-10,10); + Int_t nentries = 100000; + h2->FillRandom("f2",nentries); + //Fit h2 with original function f2 + Float_t ratio = 4*nentries/100000; + f2params[ 0] *= ratio; + f2params[ 5] *= ratio; + f2params[10] *= ratio; + f2->SetParameters(f2params); + h2->Fit("f2","N"); + TCutG *cutg = new TCutG("cutg",5); + cutg->SetPoint(0,-7,-7); + cutg->SetPoint(1, 2,-7); + cutg->SetPoint(2, 2, 2); + cutg->SetPoint(3,-7, 2); + cutg->SetPoint(4,-7,-7); + h2->Draw("lego2 0"); + h2->SetFillColor(38); + f2->SetNpx(80); + f2->SetNpy(80); + f2->Draw("surf1 same bb [cutg]"); + return c; +} diff --git a/tutorials/fit/cmaes_fit2dHist.C b/tutorials/fit/cmaes_fit2dHist.C new file mode 100644 index 0000000000000..c40683e579ea2 --- /dev/null +++ b/tutorials/fit/cmaes_fit2dHist.C @@ -0,0 +1,253 @@ +// +//+ Example to fit two histograms at the same time via TVirtualFitter +// +// To execute this tutorial, you can do: +// +// root > .x fit2dHist.C (executing via CINT, slow) +// or +// root > .x fit2dHist.C+ (executing via ACLIC , fast, with Minuit) +// root > .x fit2dHist.C+(2) (executing via ACLIC , fast, with Minuit2) +// or using the option to fit independently the 2 histos +// root > .x fit2dHist.C+(10) (via ACLIC, fast, independent fits with Minuit) +// root > .x fit2dHist.C+(12) (via ACLIC, fast, independent fits with Minuit2) +// +// Note that you can also execute this script in batch with eg, +// root -b -q "fit2dHist.C+(12)" +// +// or execute interactively from the shell +// root fit2dHist.C+ +// root "fit2dHist.C+(12)" +// +// Authors: Lorenzo Moneta, Rene Brun 18/01/2006 + +#include "TH2D.h" +#include "TF2.h" +#include "TCanvas.h" +#include "TStyle.h" +#include "TRandom3.h" +#include "TVirtualFitter.h" +#include "TList.h" +#include "TSystem.h" + +#include + +bool libloaded = false; + +double gauss2D(double *x, double *par) { + double z1 = double((x[0]-par[1])/par[2]); + double z2 = double((x[1]-par[3])/par[4]); + return par[0]*exp(-0.5*(z1*z1+z2*z2)); +} +double my2Dfunc(double *x, double *par) { + return gauss2D(x,&par[0]) + gauss2D(x,&par[5]); +} + + +// data need to be globals to be visible by fcn +TRandom3 rndm; +TH2D *h1, *h2; +Int_t npfits; + +void myFcn(Int_t & /*nPar*/, Double_t * /*grad*/ , Double_t &fval, Double_t *p, Int_t /*iflag */ ) +{ + TAxis *xaxis1 = h1->GetXaxis(); + TAxis *yaxis1 = h1->GetYaxis(); + TAxis *xaxis2 = h2->GetXaxis(); + TAxis *yaxis2 = h2->GetYaxis(); + + int nbinX1 = h1->GetNbinsX(); + int nbinY1 = h1->GetNbinsY(); + int nbinX2 = h2->GetNbinsX(); + int nbinY2 = h2->GetNbinsY(); + + double chi2 = 0; + double x[2]; + double tmp; + npfits = 0; + for (int ix = 1; ix <= nbinX1; ++ix) { + x[0] = xaxis1->GetBinCenter(ix); + for (int iy = 1; iy <= nbinY1; ++iy) { + if ( h1->GetBinError(ix,iy) > 0 ) { + x[1] = yaxis1->GetBinCenter(iy); + tmp = (h1->GetBinContent(ix,iy) - my2Dfunc(x,p))/h1->GetBinError(ix,iy); + chi2 += tmp*tmp; + npfits++; + } + } + } + for (int ix = 1; ix <= nbinX2; ++ix) { + x[0] = xaxis2->GetBinCenter(ix); + for (int iy = 1; iy <= nbinY2; ++iy) { + if ( h2->GetBinError(ix,iy) > 0 ) { + x[1] = yaxis2->GetBinCenter(iy); + tmp = (h2->GetBinContent(ix,iy) - my2Dfunc(x,p))/h2->GetBinError(ix,iy); + chi2 += tmp*tmp; + npfits++; + } + } + } + fval = chi2; +} + +void FillHisto(TH2D * h, int n, double * p) { + + + const double mx1 = p[1]; + const double my1 = p[3]; + const double sx1 = p[2]; + const double sy1 = p[4]; + const double mx2 = p[6]; + const double my2 = p[8]; + const double sx2 = p[7]; + const double sy2 = p[9]; + //const double w1 = p[0]*sx1*sy1/(p[5]*sx2*sy2); + const double w1 = 0.5; + + double x, y; + for (int i = 0; i < n; ++i) { + // generate randoms with larger gaussians + rndm.Rannor(x,y); + + double r = rndm.Rndm(1); + if (r < w1) { + x = x*sx1 + mx1; + y = y*sy1 + my1; + } + else { + x = x*sx2 + mx2; + y = y*sy2 + my2; + } + h->Fill(x,y); + + } +} + + + + +int fit2dHist(int option=1) { + + if (!libloaded) + { + gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); + gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); + libloaded = true; + } + + // create two histograms + + int nbx1 = 50; + int nby1 = 50; + int nbx2 = 50; + int nby2 = 50; + double xlow1 = 0.; + double ylow1 = 0.; + double xup1 = 10.; + double yup1 = 10.; + double xlow2 = 5.; + double ylow2 = 5.; + double xup2 = 20.; + double yup2 = 20.; + + h1 = new TH2D("h1","core",nbx1,xlow1,xup1,nby1,ylow1,yup1); + h2 = new TH2D("h2","tails",nbx2,xlow2,xup2,nby2,ylow2,yup2); + + double iniParams[10] = { 100, 6., 2., 7., 3, 100, 12., 3., 11., 2. }; + // create fit function + TF2 * func = new TF2("func",my2Dfunc,xlow2,xup2,ylow2,yup2, 10); + func->SetParameters(iniParams); + + // fill Histos + int n1 = 1000000; + int n2 = 1000000; + FillHisto(h1,n1,iniParams); + FillHisto(h2,n2,iniParams); + + // scale histograms to same heights (for fitting) + double dx1 = (xup1-xlow1)/double(nbx1); + double dy1 = (yup1-ylow1)/double(nby1); + double dx2 = (xup2-xlow2)/double(nbx2); + double dy2 = (yup2-ylow2)/double(nby2); + // scale histo 2 to scale of 1 + h2->Sumw2(); + h2->Scale( ( double(n1) * dx1 * dy1 ) / ( double(n2) * dx2 * dy2 ) ); + + bool global = false; + if (option > 10) global = true; + if (global) { + // fill data structure for fit (coordinates + values + errors) + std::cout << "Do global fit" << std::endl; + // fit now all the function together + + //The default minimizer is Minuit, you can also try Minuit2 + if (option%10 == 2) + TVirtualFitter::SetDefaultFitter("Minuit2"); + else TVirtualFitter::SetDefaultFitter("Minuit"); + TVirtualFitter * minuit = TVirtualFitter::Fitter(0,10); + for (int i = 0; i < 10; ++i) { + minuit->SetParameter(i, func->GetParName(i), func->GetParameter(i), 0.01, 0,0); + } + minuit->SetFCN(myFcn); + + double arglist[100]; + arglist[0] = 0; + // set print level + minuit->ExecuteCommand("SET PRINT",arglist,2); + + // minimize + arglist[0] = 5000; // number of function calls + arglist[1] = 0.01; // tolerance + minuit->ExecuteCommand("MIGRAD",arglist,2); + + //get result + double minParams[10]; + double parErrors[10]; + for (int i = 0; i < 10; ++i) { + minParams[i] = minuit->GetParameter(i); + parErrors[i] = minuit->GetParError(i); + } + double chi2, edm, errdef; + int nvpar, nparx; + minuit->GetStats(chi2,edm,errdef,nvpar,nparx); + + func->SetParameters(minParams); + func->SetParErrors(parErrors); + func->SetChisquare(chi2); + int ndf = npfits-nvpar; + func->SetNDF(ndf); + + // add to list of functions + h1->GetListOfFunctions()->Add(func); + h2->GetListOfFunctions()->Add(func); + } + else { + // fit independently + TVirtualFitter::SetDefaultFitter("cmaes"); + h1->Fit(func); + h2->Fit(func); + } + + // Create a new canvas. + TCanvas * c1 = new TCanvas("c1","Two HIstogram Fit example",100,10,900,800); + c1->Divide(2,2); + gStyle->SetOptFit(); + gStyle->SetStatY(0.6); + + c1->cd(1); + h1->Draw(); + func->SetRange(xlow1,ylow1,xup1,yup1); + func->DrawCopy("cont1 same"); + c1->cd(2); + h1->Draw("lego"); + func->DrawCopy("surf1 same"); + c1->cd(3); + func->SetRange(xlow2,ylow2,xup2,yup2); + h2->Draw(); + func->DrawCopy("cont1 same"); + c1->cd(4); + h2->Draw("lego"); + gPad->SetLogz(); + func->Draw("surf1 same"); + + return 0; +} diff --git a/tutorials/fit/minuit2GausFit.C b/tutorials/fit/minuit2GausFit.C index 0a4087b9357d4..758fddbfd0254 100644 --- a/tutorials/fit/minuit2GausFit.C +++ b/tutorials/fit/minuit2GausFit.C @@ -54,7 +54,7 @@ void testGausFit( std::string type = "Minuit2", int n = 1000) { c1->cd(1); cout << "\nDo Fit 1\n"; - h1->Fit("gaus","Q"); + h1->Fit("gaus","V"); h1->Draw(); c1->cd(2); cout << "\nDo Fit 2\n"; @@ -75,7 +75,7 @@ void minuit2GausFit() { int n = 1000; testGausFit("Minuit2",n); - testGausFit("Fumili2",n); + //testGausFit("Fumili2",n); } From 7e2dd23ebad24e3843404e8b47e6e0e1c4c3b010 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 21 Nov 2014 13:57:28 +0000 Subject: [PATCH 79/98] allow cmake build with CMA-ES support without pkg-config nor full install of libcmaes --- cmake/modules/FindLibCmaes.cmake | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cmake/modules/FindLibCmaes.cmake b/cmake/modules/FindLibCmaes.cmake index c5161900b3f6f..00757a145447a 100644 --- a/cmake/modules/FindLibCmaes.cmake +++ b/cmake/modules/FindLibCmaes.cmake @@ -24,12 +24,14 @@ endif ( LIBCMAES_INCLUDE_DIR AND LIBCMAES_LIBRARIES ) # in the FIND_PATH() and FIND_LIBRARY() calls if( NOT WIN32 ) find_package(PkgConfig) + pkg_check_modules(PC_LIBCMAES QUIET libcmaes) - pkg_check_modules(PC_LIBCMAES REQUIRED libcmaes) + if( PKG_CONFIG_FOUND ) + set(LIBCMAES_INCLUDE_DIR ${PC_LIBCMAES_INCLUDE_DIRS}) + set(LIBCMAES_LIBRARIES ${PC_LIBCMAES_LIBRARY_DIRS}) + set(LIBCMAES_DEFINITIONS ${PC_LIBCMAES_CFLAGS_OTHER}) + endif( PKG_CONFIG_FOUND ) - set(LIBCMAES_INCLUDE_DIR ${PC_LIBCMAES_INCLUDE_DIRS}) - set(LIBCMAES_LIBRARIES ${PC_LIBCMAES_LIBRARY_DIRS}) - set(LIBCMAES_DEFINITIONS ${PC_LIBCMAES_CFLAGS_OTHER}) endif( NOT WIN32 ) find_path(LIBCMAES_INCLUDE_DIR NAMES cmaes.h From ba771c82603421fa45fdc67d9261fcc13f73545d Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 21 Nov 2014 15:03:45 +0000 Subject: [PATCH 80/98] libcmaes and CMA-ES are OFF by default --- cmake/modules/RootBuildOptions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/RootBuildOptions.cmake b/cmake/modules/RootBuildOptions.cmake index bea18d05d66ef..e008577cc0670 100644 --- a/cmake/modules/RootBuildOptions.cmake +++ b/cmake/modules/RootBuildOptions.cmake @@ -137,7 +137,7 @@ ROOT_BUILD_OPTION(krb5 ON "Kerberos5 support, requires Kerberos libs") ROOT_BUILD_OPTION(ldap ON "LDAP support, requires (Open)LDAP libs") ROOT_BUILD_OPTION(mathmore ON "Build the new libMathMore extended math library, requires GSL (vers. >= 1.8)") ROOT_BUILD_OPTION(memstat ${memstat_defvalue} "A memory statistics utility, helps to detect memory leaks") -ROOT_BUILD_OPTION(libcmaes ON "Build the libcmaes minimizer library") +ROOT_BUILD_OPTION(libcmaes OFF "Build the libcmaes minimizer library") ROOT_BUILD_OPTION(minuit2 ${minuit2_defvalue} "Build the new libMinuit2 minimizer library") ROOT_BUILD_OPTION(monalisa ON "Monalisa monitoring support, requires libapmoncpp") ROOT_BUILD_OPTION(mysql ON "MySQL support, requires libmysqlclient") From 272d67ba4da3fdf9a86e9e55e1f9ef2f7e11128f Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 21 Nov 2014 17:25:33 +0000 Subject: [PATCH 81/98] fixed libcmaes flag in compilation --- cmake/modules/RootConfiguration.cmake | 1 + math/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake/modules/RootConfiguration.cmake b/cmake/modules/RootConfiguration.cmake index 96adf9254cde9..4cd5a87991cc4 100644 --- a/cmake/modules/RootConfiguration.cmake +++ b/cmake/modules/RootConfiguration.cmake @@ -388,6 +388,7 @@ set(buildmathmore ${value${mathmore}}) set(buildcling ${value${cling}}) set(buildroofit ${value${roofit}}) set(buildminuit2 ${value${minuit2}}) +set(buildcmaes ${value${libcmaes}}) set(buildunuran ${value${unuran}}) set(buildgdml ${value${gdml}}) set(buildhttp ${value${http}}) diff --git a/math/CMakeLists.txt b/math/CMakeLists.txt index 0f5ffab1825e5..305427933c235 100644 --- a/math/CMakeLists.txt +++ b/math/CMakeLists.txt @@ -10,7 +10,9 @@ add_subdirectory(minuit) if(minuit2) add_subdirectory(minuit2) endif() -add_subdirectory(cmaes) +if (libcmaes) + add_subdirectory(cmaes) +endif() add_subdirectory(fumili) add_subdirectory(physics) add_subdirectory(mlp) From 1806b87ed813bd44770657742cd1b84292fd8851 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Sat, 22 Nov 2014 14:06:13 +0000 Subject: [PATCH 82/98] cmake download libcmaes and eigen3, install them locally from scratch when compiling ROOT with CMA-ES support --- cmake/modules/SearchInstalledSoftware.cmake | 30 ++++++++++++++++----- etc/dictpch/makepch.sh | 2 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 2a8d4ba1a85fd..b5536df799cf7 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -476,12 +476,30 @@ if(libcmaes) message(STATUS "Looking for libcmaes") find_package(LibCmaes) if(NOT LIBCMAES_FOUND) - if(fail-on-missing) - message(FATAL_ERROR "libcmaes not found") - else() - message(STATUS "libcmaes not found. Switching off libcmaes option") - set(libcmaes OFF CACHE BOOL "" FORCE) - endif() + message(STATUS "Fetching and compiling libcmaes") + ExternalProject_Add( + eigen3 + PREFIX eigen3 + INSTALL_DIR ${CMAKE_BINARY_DIR} + URL http://bitbucket.org/eigen/eigen/get/3.2.2.tar.gz + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= + ) + ExternalProject_Add( + local_libcmaes + URL https://github.com/beniz/libcmaes/archive/master.tar.gz + PREFIX local_libcmaes + INSTALL_DIR ${CMAKE_BINARY_DIR} + CONFIGURE_COMMAND ./autogen.sh && ./configure --prefix= --with-eigen3-include=${CMAKE_BINARY_DIR}/include/eigen3 + BUILD_IN_SOURCE 1 + ) + set(LIBCMAES_INCLUDE_DIR ${CMAKE_BINARY_DIR}/include/libcmaes ${CMAKE_BINARY_DIR}/include/eigen3) + set(LIBCMAES_LIBRARIES ${CMAKE_BINARY_DIR}/lib/) + #if(fail-on-missing) + # message(FATAL_ERROR "libcmaes not found") + #else() + # message(STATUS "libcmaes not found. Switching off libcmaes option") + # set(libcmaes OFF CACHE BOOL "" FORCE) + #endif() endif() endif() diff --git a/etc/dictpch/makepch.sh b/etc/dictpch/makepch.sh index 1e922a282b1de..e538662b26f17 100755 --- a/etc/dictpch/makepch.sh +++ b/etc/dictpch/makepch.sh @@ -34,7 +34,7 @@ if ! [ -f $rootdir/$allheaders ]; then fi fi -cxxflags="-D__CLING__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DROOT_PCH -I$rootdir/include -I$rootdir/etc -I$rootdir/$cfgdir -I$rootdir/etc/cling `cat $rootdir/$cppflags`" +cxxflags="-D__CLING__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DROOT_PCH -I$rootdir/include -I$rootdir/include/libcmaes -I$rootdir/include/eigen3 -I$rootdir/etc -I$rootdir/$cfgdir -I$rootdir/etc/cling `cat $rootdir/$cppflags`" if ! [ "x$1" = "x" ]; then cxxflags="$cxxflags $1" From 4f2818f87f66b61265cf01fd7a39be2eaba5012c Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Sat, 22 Nov 2014 14:06:13 +0000 Subject: [PATCH 83/98] cmake download libcmaes and eigen3, install them locally from scratch when compiling ROOT with CMA-ES support --- cmake/modules/SearchInstalledSoftware.cmake | 30 ++++++++++++++++----- etc/dictpch/makepch.sh | 2 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 2a8d4ba1a85fd..b5536df799cf7 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -476,12 +476,30 @@ if(libcmaes) message(STATUS "Looking for libcmaes") find_package(LibCmaes) if(NOT LIBCMAES_FOUND) - if(fail-on-missing) - message(FATAL_ERROR "libcmaes not found") - else() - message(STATUS "libcmaes not found. Switching off libcmaes option") - set(libcmaes OFF CACHE BOOL "" FORCE) - endif() + message(STATUS "Fetching and compiling libcmaes") + ExternalProject_Add( + eigen3 + PREFIX eigen3 + INSTALL_DIR ${CMAKE_BINARY_DIR} + URL http://bitbucket.org/eigen/eigen/get/3.2.2.tar.gz + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= + ) + ExternalProject_Add( + local_libcmaes + URL https://github.com/beniz/libcmaes/archive/master.tar.gz + PREFIX local_libcmaes + INSTALL_DIR ${CMAKE_BINARY_DIR} + CONFIGURE_COMMAND ./autogen.sh && ./configure --prefix= --with-eigen3-include=${CMAKE_BINARY_DIR}/include/eigen3 + BUILD_IN_SOURCE 1 + ) + set(LIBCMAES_INCLUDE_DIR ${CMAKE_BINARY_DIR}/include/libcmaes ${CMAKE_BINARY_DIR}/include/eigen3) + set(LIBCMAES_LIBRARIES ${CMAKE_BINARY_DIR}/lib/) + #if(fail-on-missing) + # message(FATAL_ERROR "libcmaes not found") + #else() + # message(STATUS "libcmaes not found. Switching off libcmaes option") + # set(libcmaes OFF CACHE BOOL "" FORCE) + #endif() endif() endif() diff --git a/etc/dictpch/makepch.sh b/etc/dictpch/makepch.sh index 1e922a282b1de..e538662b26f17 100755 --- a/etc/dictpch/makepch.sh +++ b/etc/dictpch/makepch.sh @@ -34,7 +34,7 @@ if ! [ -f $rootdir/$allheaders ]; then fi fi -cxxflags="-D__CLING__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DROOT_PCH -I$rootdir/include -I$rootdir/etc -I$rootdir/$cfgdir -I$rootdir/etc/cling `cat $rootdir/$cppflags`" +cxxflags="-D__CLING__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DROOT_PCH -I$rootdir/include -I$rootdir/include/libcmaes -I$rootdir/include/eigen3 -I$rootdir/etc -I$rootdir/$cfgdir -I$rootdir/etc/cling `cat $rootdir/$cppflags`" if ! [ "x$1" = "x" ]; then cxxflags="$cxxflags $1" From d9d3945e276e13cfe5ca73004afe1f13c0ba4d4d Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 25 Nov 2014 11:31:17 +0000 Subject: [PATCH 84/98] name of export project was confusing cmake --- cmake/modules/SearchInstalledSoftware.cmake | 7 ++++--- math/cmaes/CMakeLists.txt | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index b5536df799cf7..490b6743277bc 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -485,10 +485,11 @@ if(libcmaes) CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= ) ExternalProject_Add( - local_libcmaes - URL https://github.com/beniz/libcmaes/archive/master.tar.gz - PREFIX local_libcmaes + cma + DEPENDS eigen3 + PREFIX cma INSTALL_DIR ${CMAKE_BINARY_DIR} + URL https://github.com/beniz/libcmaes/archive/master.tar.gz CONFIGURE_COMMAND ./autogen.sh && ./configure --prefix= --with-eigen3-include=${CMAKE_BINARY_DIR}/include/eigen3 BUILD_IN_SOURCE 1 ) diff --git a/math/cmaes/CMakeLists.txt b/math/cmaes/CMakeLists.txt index 50316c11729c1..3861b456096fa 100644 --- a/math/cmaes/CMakeLists.txt +++ b/math/cmaes/CMakeLists.txt @@ -13,4 +13,4 @@ link_directories(${LIBCMAES_LIBRARIES}) ROOT_GENERATE_DICTIONARY(G__cmaes *.h MODULE cmaes LINKDEF LinkDef.h) ROOT_LINKER_LIBRARY(cmaes_root *.cxx G__cmaes.cxx DEPENDENCIES MathCore Hist LIBRARIES cmaes) -ROOT_INSTALL_HEADERS() \ No newline at end of file +ROOT_INSTALL_HEADERS() From 48430550447fc6cba87f1bfe9850e4057bc48374 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 25 Nov 2014 15:25:46 +0000 Subject: [PATCH 85/98] only build libcmaes lib with no exe when build from ROOT cmake --- cmake/modules/SearchInstalledSoftware.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 490b6743277bc..32df7bbce00cd 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -490,7 +490,7 @@ if(libcmaes) PREFIX cma INSTALL_DIR ${CMAKE_BINARY_DIR} URL https://github.com/beniz/libcmaes/archive/master.tar.gz - CONFIGURE_COMMAND ./autogen.sh && ./configure --prefix= --with-eigen3-include=${CMAKE_BINARY_DIR}/include/eigen3 + CONFIGURE_COMMAND ./autogen.sh && ./configure --prefix= --with-eigen3-include=${CMAKE_BINARY_DIR}/include/eigen3 --enable-onlylib BUILD_IN_SOURCE 1 ) set(LIBCMAES_INCLUDE_DIR ${CMAKE_BINARY_DIR}/include/libcmaes ${CMAKE_BINARY_DIR}/include/eigen3) From fd43a82a74376818f817356eed2744600b54eb82 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Mon, 5 Jan 2015 07:40:02 +0000 Subject: [PATCH 86/98] added cmaes support README.md file --- math/cmaes/README.md | 126 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 math/cmaes/README.md diff --git a/math/cmaes/README.md b/math/cmaes/README.md new file mode 100644 index 0000000000000..77308054ebe31 --- /dev/null +++ b/math/cmaes/README.md @@ -0,0 +1,126 @@ +### This is support for black-box optimization with CMA-ES from within ROOT (http://root.cern.ch/drupal/). + +** This work is improved when needed, see status here: https://github.com/beniz/libcmaes/issues/13 ** + +** This work may be about to enter ROOT repository, follow integration here: +https://github.com/root-mirror/root/pull/40 ** + +libcmaes can be used from CERN's ROOT6 as a seamless replacement or addition to Minuit2 optimizer. It is designed to be used from ROOT6 **exactly** as Minuit2 is used, so code using Minuit2 should be easily run against CMA-ES. + +Below are instructions for testing it out. + +### Building ROOT6 and libcmaes +As for now, the only way to use libcmaes is from ROOT6, using the following special repository, and compiling it from sources (1): https://github.com/beniz/root + +* get ROOT6 from https://github.com/beniz/root/tree/cmaes4root_master, configure & compile it (this will take a while) (2): +```` +git clone https://github.com/beniz/root.git +cd root +``` +It is recommended to build with cmake, see below. + +#### Build with autoconf (configure) #### +For this, you need to have libcmaes installed already, see https://github.com/beniz/libcmaes/wiki +``` +./configure --enable-minuit2 --enable-roofit --enable-python --with-cmaes-incdir=/home/yourusername/include/libcmaes --with-cmaes-libdir=/home/yourusername/lib +make +```` +use make -jx where x is the number of cores on your system in order to minimize the building time. + +#### Build with cmake #### +```` +mkdir mybuild +cd mybuild +cmake ../ -Dall=on -Dtesting=on -Dlibcmaes=on +make +```` +use make -jx where x is the number of cores on your system in order to minimize the building time. + +### Running an example with CMA-ES +To run the basic fitting of a Gaussian, originally taken from Minuit2's tutorial files, do: +```` +root +.L tutorials/fit/cmaesGausFit.C++g +cmaesGausFit() +```` +You should see a plot similar to +![cmaes_gaus_fit_root_errors](https://cloud.githubusercontent.com/assets/3530657/2890890/4d96ae1c-d52d-11e3-9610-f24790b23e98.png) + +To quick test competitiveness against Minuit2: +```` +root +.L tutorials/fit/cmaesFitBench.C + cmaesFitBench() +```` +You should witness a plot similar to +![](http://juban.free.fr/stuff/libcmaes/cmaes_minuit2_competitive.png) + +### Running a benchmark comparison of CMA-ES and Minuit2 + +To run the current benchmark and visualize results, take the following steps: +```` +root +.L tutorials/fit/cmaesFullBench.C +run_experiments(10) +python math/cmaes/test/cmaesFullBench.py +```` + +This should show a series of histograms comparing results from both optimizers on a selection of problems. + +### Options to the CMA-ES minimizers within ROOT +There's built-in control for several hyper-parameters and options of CMA-ES: +* several flavors of the algorithm are available, and can be choosen at creation of the Minimizer object: +```` +TVirtualFitter::SetDefaultFitter(``acmaes''); +```` +or +```` +ROOT::Fit::Fitter fitter; +fitter.Config().SetMinimizer(``cmaes'',''acmaes''); +```` +The available algorithms are: `cmaes, ipop, bipop, acmaes, aipop, abipop, sepcmaes, sepipop, sepbipop`. + +'acmaes' should be the most appropriate in most cases, and 'sepacmaes' when the number of dimensions nears a thousand. + +The options below are not required, but can be used by filling up a MinimizerOptions object beforehand: +```` +const char *fitter = "acmaes" +TVirtualFitter::SetDefaultFitter(fitter); +ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); +opts.SetIntValue("lambda",100); +```` +Options below are not activated by default: +* 'sigma': initial step-size +* 'lambda': number of offsprings at each generation +* 'noisy': flag that updates some hyper-parameters if the objective function is noisy +* 'restarts': maximum number of restarts, only applies to ipop, bipop, aipop, abipop, sepipop and sepbipop +* 'ftarget': the objective function target that stops optimization when reached, useful when the final value is known, e.g. 0 +* 'fplot': output file in libcmaes format for later plotting of eigenvalues and state convergence, mostly for debug purposes +* 'lscaling': automatic linear scaling of parameters with auto-selection of step-size sigma, usually recommended if results are not satisfactory +* 'mt_feval': allows for parallel calls of the objective function, faster but the objective function is required to be thread-safe. + +### Using CMA-ES from RooFit +libcmaes support within ROOT extends to RooFit without effort. + +From Roofit, it is enough to set the Minimizer with +```C++ + +``` +and from PyROOT for example +```Python +RooFit.Minimizer("cmaes","acmaes") +``` + +For setting CMA-ES custom options, such as 'sigma', 'lambda' or 'lscaling', it is enough to set the options as explained in the non RooFit case: +```C++ +ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); +opts.SetIntValue("lambda",100); +``` +and from PyRoot +```Python +opt = ROOT.Math.MinimizerOptions.Default("cmaes") +opt.SetIntValue("lambda",100) +``` + +(1) more convenient ways will be provided. +(2) we recommend building support for both Minuit2 (i.e. for comparison to CMA-ES) and debug. \ No newline at end of file From b1e1ccf5c980dd262b823f96ea481ec89946d42a Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 3 Mar 2015 07:04:30 +0000 Subject: [PATCH 87/98] lower the default number of CMA-ES profile likelihood (aka Minos) iterations --- math/cmaes/src/CMAESMinimizer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 75f563a971aa4..1304c8e193920 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -647,7 +647,7 @@ namespace ROOT { if (!fWithBounds) { - le = errstats>::profile_likelihood(ffit,fCMAparams_l,fCMAsols,i,false,samplesize,ErrorDef()); + le = errstats>::profile_likelihood(ffit,fCMAparams_l,fCMAsols,i,false,samplesize,ErrorDef(),100); } else { From 0208657651e36861bf80017f9d38677fb16594c6 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 3 Mar 2015 07:04:54 +0000 Subject: [PATCH 88/98] activate full CMA-ES Root benchmark --- tutorials/fit/cmaesFullBench.C | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tutorials/fit/cmaesFullBench.C b/tutorials/fit/cmaesFullBench.C index 32b42762fb2f7..fc04c6913cdf1 100644 --- a/tutorials/fit/cmaesFullBench.C +++ b/tutorials/fit/cmaesFullBench.C @@ -964,14 +964,14 @@ void cmaesFullBench(const int &n=100, std::vector acmaes_stats; std::vector minuit2_stats; std::map mexperiments; - //mexperiments.insert(std::pair(ggauss_fit._name,&ggauss_fit)); + mexperiments.insert(std::pair(ggauss_fit._name,&ggauss_fit)); mexperiments.insert(std::pair(glorentz_fit._name,&glorentz_fit)); - /*mexperiments.insert(std::pair(gfit2._name,&gfit2)); + mexperiments.insert(std::pair(gfit2._name,&gfit2)); mexperiments.insert(std::pair(ggauss2D_fit._name,&ggauss2D_fit)); mexperiments.insert(std::pair(gfit2a._name,&gfit2a)); mexperiments.insert(std::pair(gfit2dhist._name,&gfit2dhist)); mexperiments.insert(std::pair(gcombined_fit._name,&gcombined_fit)); - mexperiments.insert(std::pair(gex3d._name,&gex3d));*/ + mexperiments.insert(std::pair(gex3d._name,&gex3d)); int nexp = mexperiments.size(); int cn = 0; std::map::iterator mit = mexperiments.begin(); From 5802811127d48a2b86e423ac052e7409a25c760d Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 3 Mar 2015 07:07:05 +0000 Subject: [PATCH 89/98] CMA-ES glue code cleanup --- math/cmaes/src/CMAESMinimizer.cxx | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 1304c8e193920..fb99d17c88207 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -37,9 +37,6 @@ using namespace libcmaes; namespace ROOT { - // registers a default empty set of extra options. - //ROOT::Math::IOptions &defIOptions = ROOT::Math::MinimizerOptions::Default("cmaes"); - namespace cmaes { @@ -476,12 +473,6 @@ namespace ROOT if (fWithBounds) { Info("CMAESMinimizer","Minimizing with bounds and linear scaling"); - /*ProgressFunc>,CMASolutions> pfunc = [](const CMAParameters> &cmaparams, const CMASolutions &cmasols) - { - std::cout << "iter=" << cmasols.niter() << " / evals=" << cmasols.nevals() << " / f-value=" << cmasols.best_candidate().get_fvalue() << " / sigma=" << cmasols.sigma() << std::endl; - std::cout << "best x=" << cmaparams.get_gp().pheno(cmasols.best_candidate().get_x_dvec()).transpose() << std::endl; - return 0; - };*/ GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); @@ -490,7 +481,6 @@ namespace ROOT } else { - //ProgressFunc,CMASolutions> pfunc = [](const CMAParameters<> &cmaparams, const CMASolutions &cmasols) { return 0; }; Info("CMAESMinimizer","Minimizing with linear scaling"); GenoPheno gp(vscaling,vshift); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); @@ -569,7 +559,6 @@ namespace ROOT const double* TCMAESMinimizer::Errors() const { fErrors.clear(); - //const double* diag = fCMAsols._cov.diagonal().data(); dVec vgdiag; if (fWithLinearScaling) { From 1d0d235185c721ad56bd4f12570a5203c945f35a Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 3 Mar 2015 07:23:40 +0000 Subject: [PATCH 90/98] added support for novel CMA-ES options: uncertainty handling and elitism --- math/cmaes/inc/CMAESMinimizer.h | 4 +++- math/cmaes/src/CMAESMinimizer.cxx | 18 +++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 98b96d2ee22d5..606e16594bcad 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -125,7 +125,9 @@ namespace ROOT const std::string &fplot, const bool &withnumgradient, const bool &mtfeval, - const bool &quiet); + const bool &quiet, + const int &elitist, // 0: off (default), then 1, 2 or 3 + const bool &uh); /** method to perform the minimization. diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index fb99d17c88207..6121a1ff34235 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -344,7 +344,9 @@ namespace ROOT const std::string &fplot, const bool &withnumgradient, const bool &mtfeval, - const bool &quiet) + const bool &quiet, + const int &elitist, + const bool &uh) { cmaparams.set_algo(fMinimizer); if (gDebug > 0 || !quiet) @@ -365,6 +367,8 @@ namespace ROOT cmaparams.set_fplot(fplot); cmaparams.set_gradient(withnumgradient); cmaparams.set_mt_feval(mtfeval); + cmaparams.set_elitism(elitist); + cmaparams.set_uh(uh); } bool TCMAESMinimizer::Minimize() @@ -443,6 +447,8 @@ namespace ROOT int mtfeval = 0; // parallel execution of objective function int quiet = 0; int seed = 0; + int elitist = 0; // elitism: forces best solution in various manners + int uh = 0; // uncertainty handling, for noisy functions // set hyper-parameters according to IOptions object. if (cmaesOpt) @@ -458,6 +464,8 @@ namespace ROOT cmaesOpt->GetValue("mt_feval",mtfeval); cmaesOpt->GetValue("quiet",quiet); cmaesOpt->GetValue("seed",seed); + cmaesOpt->GetValue("elitist",elitist); + cmaesOpt->GetValue("uh",uh); } if (gDebug > 0) @@ -475,7 +483,7 @@ namespace ROOT Info("CMAESMinimizer","Minimizing with bounds and linear scaling"); GenoPheno gp(vscaling,vshift,&fLBounds.front(),&fUBounds.front()); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet,elitist,uh); fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); fCMAparams_lb = cmaparams; } @@ -484,7 +492,7 @@ namespace ROOT Info("CMAESMinimizer","Minimizing with linear scaling"); GenoPheno gp(vscaling,vshift); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet,elitist,uh); fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); fCMAparams_l = cmaparams; } @@ -496,7 +504,7 @@ namespace ROOT Info("CMAESMinimizer","Minimizing with bounds"); GenoPheno gp(&fLBounds.front(),&fUBounds.front(),fDim); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed,gp); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet,elitist,uh); fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); fCMAparams_b = cmaparams; } @@ -504,7 +512,7 @@ namespace ROOT { Info("CMAESMinimizer","Minimizing without bounds or linear scaling"); CMAParameters> cmaparams(fDim,&fInitialX.front(),sigma0scaled,lambda,seed); - SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet); + SetMParameters(cmaparams,maxiter,maxfevals,noisy,nrestarts,ftarget,fplot,withnumgradient,mtfeval,quiet,elitist,uh); fCMAsols = libcmaes::cmaes>(ffit,cmaparams,CMAStrategy>::_defaultPFunc,fWithGradient?gfit:nullptr); fCMAparams = cmaparams; } From fefa75f17a4616a488cd22fb63a9478419ff4d40 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Tue, 3 Mar 2015 07:23:55 +0000 Subject: [PATCH 91/98] cleanup of the CMA-ES tutorial fit examples --- tutorials/fit/cmaesFitBench.C | 8 -------- tutorials/fit/cmaesFitBench2D.C | 8 -------- tutorials/fit/cmaesGausFit.C | 2 -- tutorials/fit/cmaes_fit2a.C | 3 --- tutorials/fit/cmaes_fit2dHist.C | 9 --------- 5 files changed, 30 deletions(-) diff --git a/tutorials/fit/cmaesFitBench.C b/tutorials/fit/cmaesFitBench.C index 3393b00bcc93d..fc070af89b756 100644 --- a/tutorials/fit/cmaesFitBench.C +++ b/tutorials/fit/cmaesFitBench.C @@ -29,8 +29,6 @@ TF1 *fitFcn; TH1 *histo; -bool libloaded = false; - // Quadratic background function Double_t background(Double_t *x, Double_t *par) { return par[0] + par[1]*x[0] + par[2]*x[0]*x[0]; @@ -101,12 +99,6 @@ void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass, Double_t sigma, In } void cmaesFitBench(Int_t npass=20, Double_t sigma=0.1, Int_t lambda=-1) { - if (!libloaded) - { - gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); - gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); - libloaded = true; - } TH1::AddDirectory(kFALSE); TCanvas *c1 = new TCanvas("FitBench","Fitting Demo",10,10,900,900); c1->Divide(2,2); diff --git a/tutorials/fit/cmaesFitBench2D.C b/tutorials/fit/cmaesFitBench2D.C index f84a0d163db52..52b7f2bd4c442 100644 --- a/tutorials/fit/cmaesFitBench2D.C +++ b/tutorials/fit/cmaesFitBench2D.C @@ -23,8 +23,6 @@ TF2 *fitFcn; TH2D *histo; -bool libloaded = false; - // Quadratic background function Double_t gaus2D(Double_t *x, Double_t *par) { double t1 = x[0] - par[1]; @@ -67,12 +65,6 @@ void DoFit(const char* fitter, TVirtualPad *pad, Int_t npass) { } void cmaesFitBench2D(int n = 100000) { - if (!libloaded) - { - gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); - gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); - libloaded = true; - } TH1::AddDirectory(kFALSE); TCanvas *c1 = new TCanvas("c1","Fitting Demo",10,10,900,900); c1->Divide(2,2); diff --git a/tutorials/fit/cmaesGausFit.C b/tutorials/fit/cmaesGausFit.C index 178a16932e1b6..7ddea883f468d 100644 --- a/tutorials/fit/cmaesGausFit.C +++ b/tutorials/fit/cmaesGausFit.C @@ -86,8 +86,6 @@ void testGausFit( std::string type = "cmaes", int n = 1000) { void cmaesGausFit() { if (!libloaded) { - gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); - gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); libloaded = true; } int n = 1000; diff --git a/tutorials/fit/cmaes_fit2a.C b/tutorials/fit/cmaes_fit2a.C index 612893be4843e..3911b4316e057 100644 --- a/tutorials/fit/cmaes_fit2a.C +++ b/tutorials/fit/cmaes_fit2a.C @@ -39,15 +39,12 @@ Double_t fun2(Double_t *x, Double_t *par) { TCanvas *fit2a(const char *fitter="cmaes") { if (!libloaded) { - gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); - gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); libloaded = true; } TVirtualFitter::SetDefaultFitter(fitter); ROOT::Math::IOptions &opts = ROOT::Math::MinimizerOptions::Default(fitter); - //ROOT::Math::IOptions *opts = ROOT::Math::MinimizerOptions::FindDefault(fitter); //opts.SetIntValue("lambda",100); opts.SetNamedValue("fplot","fit2a.dat"); diff --git a/tutorials/fit/cmaes_fit2dHist.C b/tutorials/fit/cmaes_fit2dHist.C index c40683e579ea2..607aaff2f0e02 100644 --- a/tutorials/fit/cmaes_fit2dHist.C +++ b/tutorials/fit/cmaes_fit2dHist.C @@ -31,8 +31,6 @@ #include -bool libloaded = false; - double gauss2D(double *x, double *par) { double z1 = double((x[0]-par[1])/par[2]); double z2 = double((x[1]-par[3])/par[4]); @@ -127,13 +125,6 @@ void FillHisto(TH2D * h, int n, double * p) { int fit2dHist(int option=1) { - if (!libloaded) - { - gSystem->Load("/usr/lib/x86_64-linux-gnu/libglog.so"); - gSystem->Load("/usr/lib/x86_64-linux-gnu/libgflags.so"); - libloaded = true; - } - // create two histograms int nbx1 = 50; From f67a502e225902e89a1a968e3c7db2ce9c09fdfa Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 6 Mar 2015 09:03:05 +0000 Subject: [PATCH 92/98] connected libcmaes contour function --- math/cmaes/inc/CMAESMinimizer.h | 1 - math/cmaes/src/CMAESMinimizer.cxx | 40 +++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index 606e16594bcad..d9abde5aac122 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -251,7 +251,6 @@ namespace ROOT find the contour points (xi,xj) of the function for parameter i and j around the minimum The contour will be find for value of the function = Min + ErrorUp(); */ - //TODO virtual bool Contour(unsigned int i, unsigned int j, unsigned int & npoints, double *xi, double *xj); diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 6121a1ff34235..972b99141dbc7 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -675,8 +675,44 @@ namespace ROOT bool TCMAESMinimizer::Contour(unsigned int i, unsigned int j, unsigned int &npoints, double *xi, double *xj) { - //TODO. - return false; + FitFunc ffit = [this](const double *x, const int N) + { + return (*fObjFunc)(x); + }; + + contour ct; + if (fWithLinearScaling) + { + if (!fWithBounds) + { + ct = errstats>::contour_points(ffit,i,j,npoints,ErrorDef(), + fCMAparams_l,fCMAsols,0.1,100); + } + else + { + ct = errstats>::contour_points(ffit,i,j,npoints,ErrorDef(), + fCMAparams_lb,fCMAsols,0.1,100); + } + } + else + { + if (!fWithBounds) + { + ct = errstats>::contour_points(ffit,i,j,npoints,ErrorDef(), + fCMAparams,fCMAsols,0.1,100); + } + else + { + ct = errstats>::contour_points(ffit,i,j,npoints,ErrorDef(), + fCMAparams_b,fCMAsols,0.1,100); + } + } + for (size_t i=0;i Date: Fri, 6 Mar 2015 14:55:29 +0100 Subject: [PATCH 93/98] use libcmaes simplified algo setter --- math/cmaes/inc/CMAESMinimizer.h | 2 +- math/cmaes/src/CMAESMinimizer.cxx | 22 ++-------------------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index d9abde5aac122..ee7abe80dc74c 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -285,7 +285,7 @@ namespace ROOT private: unsigned int fDim = 0; // dimension of the function to be minimized unsigned int fFreeDim = 0; // Number of free dimensions. - int fMinimizer = CMAES_DEFAULT; // minimizer algo. + std::string fMinimizer = "cmaes"; // minimizer algo. const ROOT::Math::IMultiGenFunction *fObjFunc = nullptr; const ROOT::Math::IMultiGradFunction *fObjFuncGrad = nullptr; std::vector fLBounds; // Lower bounds of variables diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 972b99141dbc7..0d47cc58dd743 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -51,24 +51,7 @@ namespace ROOT std::string algoname(type); // tolower() is not an std function (Windows) std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int(*)(int)) tolower ); - if (algoname == "cmaes") - fMinimizer = CMAES_DEFAULT; - else if (algoname == "ipop") - fMinimizer = IPOP_CMAES; - else if (algoname == "bipop") - fMinimizer = BIPOP_CMAES; - else if (algoname == "acmaes") - fMinimizer = aCMAES; - else if (algoname == "aipop") - fMinimizer = aIPOP_CMAES; - else if (algoname == "abipop") - fMinimizer = aBIPOP_CMAES; - else if (algoname == "sepcmaes") - fMinimizer = sepCMAES; - else if (algoname == "sepipop") - fMinimizer = sepIPOP_CMAES; - else if (algoname == "sepbipop") - fMinimizer = sepBIPOP_CMAES; + fMinimizer = algoname; } TCMAESMinimizer::TCMAESMinimizer(const TCMAESMinimizer &m) @@ -88,7 +71,6 @@ namespace ROOT void TCMAESMinimizer::Clear() { - std::cout << "clearing up minimizer\n"; fCMAsols = CMASolutions(); fCMAparams = CMAParameters>(); fCMAparams_b = CMAParameters>(); @@ -348,7 +330,7 @@ namespace ROOT const int &elitist, const bool &uh) { - cmaparams.set_algo(fMinimizer); + cmaparams.set_str_algo(fMinimizer); if (gDebug > 0 || !quiet) cmaparams.set_quiet(false); else cmaparams.set_quiet(true); From 7531a86ba99ad607ae75ef1f09d0ecaf20f9bcb3 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 6 Mar 2015 16:23:36 +0000 Subject: [PATCH 94/98] cleared compilation warnings of CMA-ES Minimizer --- math/cmaes/inc/CMAESMinimizer.h | 2 +- math/cmaes/src/CMAESMinimizer.cxx | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index ee7abe80dc74c..e4d6ddf6caf8d 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -279,7 +279,7 @@ namespace ROOT /// set storage level = 1 : store all iteration states (default) /// = 0 : store only first and last state to save memory - //TODO. + // N/A void SetStorageLevel(int level); private: diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 0d47cc58dd743..89ad6e7f16895 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -54,10 +54,10 @@ namespace ROOT fMinimizer = algoname; } - TCMAESMinimizer::TCMAESMinimizer(const TCMAESMinimizer &m) + /*TCMAESMinimizer::TCMAESMinimizer(const TCMAESMinimizer &m) :Minimizer(),fDim(0),fFreeDim(0),fWithBounds(false),fWithGradient(false) { - } + }*/ TCMAESMinimizer& TCMAESMinimizer::operator = (const TCMAESMinimizer &rhs) { @@ -197,6 +197,7 @@ namespace ROOT { SetVariable(ivar,name,val,0.0); fFixedVariables.insert(std::pair(ivar,val)); + return true; } bool TCMAESMinimizer::SetVariableValue(unsigned int ivar, double val ) @@ -275,7 +276,10 @@ namespace ROOT bool TCMAESMinimizer::FixVariable(unsigned int ivar) { + if (ivar >= fInitialX.size()) + return false; fFixedVariables.insert(std::pair(ivar,fInitialX.at(ivar))); // XXX: sets initial variable. + return true; } bool TCMAESMinimizer::IsFixedVariable(unsigned int ivar) const @@ -312,7 +316,7 @@ namespace ROOT int TCMAESMinimizer::VariableIndex(const std::string &name) const { - for (unsigned int i=0;i(std::cout," ")); std::cout << std::endl;*/ + (void)N; return (*fObjFunc)(x); }; @@ -533,7 +538,7 @@ namespace ROOT x = bc.get_x_pheno_dvec>(fCMAparams_b); else x = bc.get_x_dvec(); } - for (int i=0;i Date: Fri, 6 Mar 2015 16:24:12 +0000 Subject: [PATCH 95/98] disabling libcmaes surrogates as unused in ROOT and for faster build of the library --- cmake/modules/SearchInstalledSoftware.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 45a7d3ee98c95..ce26debd3e762 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -496,7 +496,7 @@ if(libcmaes) PREFIX cma INSTALL_DIR ${CMAKE_BINARY_DIR} URL https://github.com/beniz/libcmaes/archive/master.tar.gz - CONFIGURE_COMMAND ./autogen.sh && ./configure --prefix= --with-eigen3-include=${CMAKE_BINARY_DIR}/include/eigen3 --enable-onlylib + CONFIGURE_COMMAND ./autogen.sh && ./configure --prefix= --with-eigen3-include=${CMAKE_BINARY_DIR}/include/eigen3 --enable-onlylib --disable-surrog BUILD_IN_SOURCE 1 ) set(LIBCMAES_INCLUDE_DIR ${CMAKE_BINARY_DIR}/include/libcmaes ${CMAKE_BINARY_DIR}/include/eigen3) From ef9b055c783fb72443e5e55cf15c9a43691053b1 Mon Sep 17 00:00:00 2001 From: Emmanuel Benazera Date: Fri, 6 Mar 2015 16:58:28 +0000 Subject: [PATCH 96/98] added Scan function to CMAESMinimizer --- math/cmaes/inc/CMAESMinimizer.h | 1 - math/cmaes/src/CMAESMinimizer.cxx | 51 +++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/math/cmaes/inc/CMAESMinimizer.h b/math/cmaes/inc/CMAESMinimizer.h index e4d6ddf6caf8d..a71eb3e96a78f 100644 --- a/math/cmaes/inc/CMAESMinimizer.h +++ b/math/cmaes/inc/CMAESMinimizer.h @@ -244,7 +244,6 @@ namespace ROOT scan a parameter i around the minimum. A minimization must have been done before, return false if it is not the case */ - //TODO virtual bool Scan(unsigned int i, unsigned int & nstep, double * x, double * y, double xmin = 0, double xmax = 0); /** diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 89ad6e7f16895..764269b1ec3f6 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -658,8 +658,55 @@ namespace ROOT bool TCMAESMinimizer::Scan(unsigned int i, unsigned int &nstep, double *x, double *y, double xmin, double xmax) { - //TODO. - return false; + std::vector> result; + std::vector params = fValues; + double amin = MinValue(); + result.push_back(std::pair(params[i],amin)); + + double low=xmin, high=xmax; + if (low <= high && nstep-1 >= 2) + { + if (low == 0 && high == 0) + { + low = fValues[i] - 2.0*fErrors.at(i); + high = fValues[i] + 2.0*fErrors.at(i); + } + + if (low == 0 && high == 0 + && (fLBounds[i] > -std::numeric_limits::max() + || fUBounds[i] < std::numeric_limits::max())) + { + if (fLBounds[i] > -std::numeric_limits::max()) + low = fLBounds[i]; + if (fUBounds[i] < std::numeric_limits::max()) + high = fUBounds[i]; + } + + if (fLBounds[i] > -std::numeric_limits::max() + || fUBounds[i] < std::numeric_limits::max()) + { + if (fLBounds[i] > -std::numeric_limits::max()) + low = std::max(low,fLBounds[i]); + if (fUBounds[i] < std::numeric_limits::max()) + high = std::min(high,fUBounds[i]); + } + + double x0 = low; + double stp = (high-low) / static_cast(nstep-2); + for (unsigned int j=0;j(params[i],fval)); + } + } + + for (int s=0;s Date: Mon, 9 Mar 2015 07:56:36 +0000 Subject: [PATCH 97/98] using libcmaes errors() call for standard deviation --- math/cmaes/src/CMAESMinimizer.cxx | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/math/cmaes/src/CMAESMinimizer.cxx b/math/cmaes/src/CMAESMinimizer.cxx index 764269b1ec3f6..0d074f800954b 100644 --- a/math/cmaes/src/CMAESMinimizer.cxx +++ b/math/cmaes/src/CMAESMinimizer.cxx @@ -554,25 +554,21 @@ namespace ROOT const double* TCMAESMinimizer::Errors() const { fErrors.clear(); - dVec vgdiag; + dVec verrors; if (fWithLinearScaling) { if (fWithBounds) - { - vgdiag = fCMAparams_lb.get_gp().pheno(dVec(fCMAsols.sigma()*fCMAsols.cov_ref().diagonal())); - } - else - { - vgdiag = fCMAparams_l.get_gp().pheno(dVec(fCMAsols.sigma()*fCMAsols.cov_ref().diagonal())); - } + verrors = fCMAsols.errors(fCMAparams_lb); + else verrors = fCMAsols.errors(fCMAparams_l); } - else if (fWithBounds) + else { - vgdiag = fCMAparams_b.get_gp().pheno(dVec(fCMAsols.sigma()*fCMAsols.cov_ref().diagonal())); + if (fWithBounds) + verrors = fCMAsols.errors(fCMAparams_b); + else verrors = fCMAsols.errors(fCMAparams); } - else vgdiag = fCMAsols.sigma()*fCMAsols.cov_ref().diagonal(); for (int i=0;i<(int)fDim;i++) - fErrors.push_back(std::sqrt(std::abs(vgdiag(i)))); // abs for numerical errors that bring the sqrt below 0. + fErrors.push_back(verrors(i)); return &fErrors.front(); } @@ -701,7 +697,7 @@ namespace ROOT } } - for (int s=0;s Date: Tue, 10 Mar 2015 13:25:07 +0100 Subject: [PATCH 98/98] added proper funding reference of the CMA-ES integration work --- math/cmaes/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/math/cmaes/README.md b/math/cmaes/README.md index 77308054ebe31..3830e9dcebcbd 100644 --- a/math/cmaes/README.md +++ b/math/cmaes/README.md @@ -1,8 +1,10 @@ ### This is support for black-box optimization with CMA-ES from within ROOT (http://root.cern.ch/drupal/). +This work was supported by the ANR-2010-COSI-002 grant of the French NationalA Research Agency. + ** This work is improved when needed, see status here: https://github.com/beniz/libcmaes/issues/13 ** -** This work may be about to enter ROOT repository, follow integration here: +** This work may be about to be merged into ROOT repository, follow integration here: https://github.com/root-mirror/root/pull/40 ** libcmaes can be used from CERN's ROOT6 as a seamless replacement or addition to Minuit2 optimizer. It is designed to be used from ROOT6 **exactly** as Minuit2 is used, so code using Minuit2 should be easily run against CMA-ES.