Skip to content

Updated support for CMA-ES minimizer based on libcmaes #7044

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 102 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
3822155
first cmaes addition
beniz May 5, 2014
d5bcdbd
adding cmaes repository
beniz May 6, 2014
fc4cb4d
added cmaes plugin
May 6, 2014
ea48ab9
first working auto-loaded cmaes
May 6, 2014
b26ba26
fixed cmaes wrapper + added likelihood gaussian fit to tutorial
May 6, 2014
d1cf676
connecting error estimates to cmaes wrapper
May 6, 2014
f8fa37f
default CMA-ES progress function set to no output
May 15, 2014
8f4a6fb
added support for box-type constraints with CMA-ES
May 16, 2014
064e2d7
added support to multiple flavors of CMA-ES
May 19, 2014
b86a301
added 1D histograms fitting benchmark for CMA-ES
May 19, 2014
0b67e07
fixed loading of libraries in CMA-ES tutorial hist fit
May 19, 2014
9f24748
fixed status in libcmaes wrapper
May 19, 2014
7f0bf46
fixed initialization of parameters with CMA-ES
May 20, 2014
3422ef4
added 2D bench for cmaes
May 20, 2014
aa18df9
added explanations to hist 1D fit for cmaes
May 20, 2014
70e1ed9
fixed parameters init for CMA-ES after refactoring of the libcmaes
May 21, 2014
05fb18e
provides error to true in CMAESMinimizer.h + preparing for fixed para…
May 21, 2014
34e619e
set default sigma0 for CMA-ES as the max step size across parameters
May 26, 2014
3dec521
fixed multiple loading of external lib in fit tutorial for CMA-ES
May 26, 2014
dd16df8
introduced first MINOS version for CMA-ES + added control of ftoleran…
May 26, 2014
a6e12ed
added to CMA-ES packagte the same tests that are available for Minuit2
May 26, 2014
cf4db6a
fixes and additions to current set of fit tutorials for CMA-ES + new …
May 26, 2014
979f0f3
connected fUp to CMA-ES confidence interval (minos) computations
May 27, 2014
68d6bf9
added control of max iterations and max functions eval to CMA-ES thro…
May 27, 2014
62770e9
did bump the default max function budget for CMA-ES
May 27, 2014
da653ef
added support for MinimizerOptions with cmaes, fixes #4
Jun 16, 2014
be005d8
using conservative min initial step-size value across all parameters …
Jun 16, 2014
e2a31e4
adapted tutorials to new cmaes performances
Jun 16, 2014
11f339a
added support for gradient information with cmaes when available
Jun 16, 2014
76c0566
added cmaes full bench tutorial script
Jun 17, 2014
6d38217
added more examples + fixes to cmaes bench script
Jun 18, 2014
b94822f
added support for cmaes / minuit2 budget and cpu ratio to benchmark
Jun 18, 2014
8a101dc
fixed settings of fixed variables in cmaes minimizer
Jun 18, 2014
3e1e5c8
fixed clearing of parameter object in cmaes wrapper
Jun 19, 2014
40c4652
new scheme in cmaes benchmark in order to compare algorithms on exact…
Jun 19, 2014
de7c095
added new functions to cmaes benchmark, in new format
Jun 19, 2014
d6114c3
added combined fit cmaes benchmark to new format
Jun 19, 2014
1c75402
completed migration of cmaes benchmarks
Jun 19, 2014
599c633
added control of number of cmaes benchmark loops over functions
Jun 19, 2014
3d5ee0b
first release of the cmaes / minuit2 benchmark tool and visualization
Jun 20, 2014
dce5cac
added support for Edm to ROOT with CMA-ES, closes #6
Jun 24, 2014
b52a4ad
filled up missing functions in CMA-ES minimizer wrapper
Jun 24, 2014
e30f82e
made CMA-ES minimizer's status compatible with those of Minuit2, clos…
Jun 24, 2014
cb014cf
clean up of CMA-ES minimizer header
Jun 24, 2014
d28ecf4
logscale + fixes to benchmark suite for CMA-ES and plot
Jun 24, 2014
d0b2f92
improvements to CMA-ES benchmark suite
Jun 24, 2014
6c0b546
CMA-ES benchmark suite support for multiple lambda values
Jun 25, 2014
8a42c51
logging of freeDim variable
Jun 25, 2014
f1c0d99
CMA-ES benchmark suite with multiple lambda values
Jun 25, 2014
af1dff8
reactivate all problems on CMA-ES benchmark
Jun 25, 2014
2c38cba
added linear scaling of input parameters to CMA-ES Minimizer, ref #5
Jun 27, 2014
90490a3
added support for sigma as option to CMA-ES Minimizer
Jun 27, 2014
45d9ec5
added optional linear scaling to CMA-ES Minimizer, ref #5
Jun 27, 2014
63f1a2a
added support for optional linear scaling to CMA-ES benchmark suite, …
Jun 27, 2014
bbef414
updated CMA-ES lorentz tutorial with control of sigma and lambda
Jun 27, 2014
2b54859
fixed sigma0 as conservative value when linear scaling is not activat…
Jul 1, 2014
8216cf4
added computation of error bounds when geno/pheno tranform is active …
Jul 2, 2014
bb76c2a
refactoring for new Minimizer getters for fTol, fUp and fMaxIter
Jul 7, 2014
befc81b
added support of numerical gradient injection to cma-es wrapper
Jul 11, 2014
742edc9
change for setting edm with cma-es
Jul 11, 2014
9653b9d
update to the minuit/cmaes benchmark
Aug 18, 2014
2e91b1b
major fix to CMA-ES / Minuit2 benchmark
Aug 20, 2014
e126cb5
updated cmaes due to new setters/getters in libcmaes
Sep 9, 2014
df89432
merge with stash
Sep 9, 2014
8c35698
fixed previous commit
Sep 9, 2014
1518c3f
fixed access to private cmaes pli members
Sep 9, 2014
e60aced
added support for multihreaded objective function calls to CMA-ES fro…
Sep 15, 2014
02f8d38
added support for control of the quiet option of libcmaes through Min…
Sep 18, 2014
6c24145
cmaes: added support for seed as an option + added example of a custo…
Sep 18, 2014
877f001
cmaes: fixed activation of gradient function when available from with…
Sep 19, 2014
dd2232c
fix wrt to cmaes API
Nov 8, 2014
e75c2fe
cmaes working with cmake
Nov 10, 2014
8800eda
fixes for cmake and configure building systems with cmaes
Nov 10, 2014
6737f0e
fix for new cmaes pli accesors
Nov 12, 2014
cae5669
Support for CMA-ES minimizer based on libcmaes
Nov 18, 2014
9c59ba5
allow cmake build with CMA-ES support without pkg-config nor full ins…
Nov 21, 2014
2cd13ce
libcmaes and CMA-ES are OFF by default
Nov 21, 2014
fb6735b
fixed libcmaes flag in compilation
Nov 21, 2014
d3baabe
cmake download libcmaes and eigen3, install them locally from scratch…
Nov 22, 2014
19adf9d
name of export project was confusing cmake
beniz Nov 25, 2014
0c09249
only build libcmaes lib with no exe when build from ROOT cmake
beniz Nov 25, 2014
8d9dc92
added cmaes support README.md file
Jan 5, 2015
cab10b3
lower the default number of CMA-ES profile likelihood (aka Minos) ite…
Mar 3, 2015
f3b9fda
activate full CMA-ES Root benchmark
Mar 3, 2015
9e3f6cd
CMA-ES glue code cleanup
Mar 3, 2015
e897163
added support for novel CMA-ES options: uncertainty handling and elitism
Mar 3, 2015
b672a5c
cleanup of the CMA-ES tutorial fit examples
Mar 3, 2015
56d2821
connected libcmaes contour function
Mar 6, 2015
cf516ca
use libcmaes simplified algo setter
Mar 6, 2015
9ea683e
cleared compilation warnings of CMA-ES Minimizer
Mar 6, 2015
6399d49
disabling libcmaes surrogates as unused in ROOT and for faster build …
Mar 6, 2015
e315e06
added Scan function to CMAESMinimizer
Mar 6, 2015
d9ddb00
using libcmaes errors() call for standard deviation
Mar 9, 2015
c88245c
added proper funding reference of the CMA-ES integration work
Mar 10, 2015
f8a72c7
fixed TF1 merge
beniz Apr 17, 2017
4e9c057
cmaes ROOT_USE_PACKAGE removal
beniz Apr 17, 2017
1edb454
removed backup file
beniz Apr 18, 2017
00fa9b7
buildcmaes in alphabetical order
beniz Apr 18, 2017
41d376a
fixed Root main URL in cmaes module README
beniz Apr 18, 2017
51b16e9
removed protectors around cmaes minimizer headers
beniz Apr 18, 2017
3556ff0
Apply some fixes after merging CMAES branch
lmoneta Jan 14, 2021
492a08f
Fix configuration for cmaes by looking also for Eigen3 that is needed…
lmoneta Jan 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
53 changes: 53 additions & 0 deletions cmake/modules/FindLibcmaes.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# - 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, <[email protected]>
#
# 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 QUIET 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 )

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 )
1 change: 1 addition & 0 deletions cmake/modules/RootBuildOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ ROOT_BUILD_OPTION(http ON "Enable suppport for HTTP server")
ROOT_BUILD_OPTION(fcgi OFF "Enable FastCGI suppport in HTTP server")
ROOT_BUILD_OPTION(imt ON "Enable support for implicit multi-threading via Intel® Thread Bulding Blocks (TBB)")
ROOT_BUILD_OPTION(jemalloc OFF "Use jemalloc memory allocator")
ROOT_BUILD_OPTION(libcmaes OFF "Build the libcmaes minimizer library")
ROOT_BUILD_OPTION(libcxx OFF "Build using libc++")
ROOT_BUILD_OPTION(macos_native OFF "Disable looking for libraries, includes and binaries in locations other than a native installation (MacOS only)")
ROOT_BUILD_OPTION(mathmore ON "Build libMathMore extended math library (requires GSL)")
Expand Down
1 change: 1 addition & 0 deletions cmake/modules/RootConfiguration.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ set(gslflags)

set(shadowpw ${value${shadowpw}})
set(buildmathmore ${value${mathmore}})
set(buildcmaes ${value${libcmaes}})
set(buildroofit ${value${roofit}})
set(buildminuit2 ${value${minuit2}})
set(buildunuran ${value${unuran}})
Expand Down
48 changes: 46 additions & 2 deletions cmake/modules/SearchInstalledSoftware.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,50 @@ if(sqlite)
endif()
endif()

#---Check for Libcmaes-------------------------------------------------------------------
if(libcmaes)
message(STATUS "Looking for libcmaes")
find_package(Libcmaes)
if (LIBCMAES_FOUND)
#we need also eigen3
find_package(Eigen3)
if (NOT EIGEN3_FOUND)
message(STATUS "Eigen3 not found. Cannot use libcmaes")
set(LIBCMAES_FOUND 0)
endif()
endif()
#here for builtin cmaes (not ful;ly implemented yet)
if(NOT LIBCMAES_FOUND AND BUILTIN_CMAES)
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=<INSTALL_DIR>
)
ExternalProject_Add(
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=<INSTALL_DIR> --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)
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()
else()
message(STATUS "libcmaes found in ${LIBCMAES_LIBRARIES}")
endif()

#---Check for Pythia6-------------------------------------------------------------------
if(pythia6)
message(STATUS "Looking for Pythia6")
Expand Down Expand Up @@ -1571,9 +1615,9 @@ if(cuda OR tmva-gpu)
### look for package CuDNN
if (cudnn)
if (fail-on-missing)
find_package(CuDNN REQUIRED)
find_package(CUDNN REQUIRED)
else()
find_package(CuDNN)
find_package(CUDNN)
endif()
if (CUDNN_FOUND)
message(STATUS "CuDNN library found: " ${CUDNN_LIBRARIES})
Expand Down
5 changes: 5 additions & 0 deletions config/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,11 @@ BUILDROOFIT := @buildroofit@

BUILDMINUIT2 := @buildminuit2@

BUILDCMAES := @buildcmaes@
CMAESINCDIR := $(filter-out -I/usr/include, @cmaesincdir@)
CMAESLIBDIR := @cmaeslibdir@
CMAESLIB := -lcmaes

BUILDUNURAN := @buildunuran@

BUILDVC := @buildvc@
Expand Down
4 changes: 2 additions & 2 deletions etc/plugins/ROOT@@Math@@Minimizer/P010_Minuit2Minimizer.C
Original file line number Diff line number Diff line change
@@ -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 *)");
}
5 changes: 5 additions & 0 deletions etc/plugins/ROOT@@Math@@Minimizer/P090_TCMAESMinimizer.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
void P090_TCMAESMinimizer()
{
gPluginMgr->AddHandler("ROOT::Math::Minimizer", "cmaes", "ROOT::cmaes::TCMAESMinimizer",
"Cmaes", "TCMAESMinimizer(const char *)");
}
3 changes: 3 additions & 0 deletions math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ add_subdirectory(minuit)
if(minuit2)
add_subdirectory(minuit2)
endif()
if (libcmaes)
add_subdirectory(cmaes)
endif()
add_subdirectory(fumili)
add_subdirectory(physics)
if(mlp)
Expand Down
25 changes: 25 additions & 0 deletions math/cmaes/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
############################################################################
# CMakeLists.txt file for building ROOT math/cmaes package
############################################################################

add_definitions(-DWARNINGMSG -DUSE_ROOT_ERROR)

include_directories(${LIBCMAES_INCLUDE_DIR} ${EIGEN3_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()

ROOT_STANDARD_LIBRARY_PACKAGE(Cmaes
HEADERS
CMAESMinimizer.h
SOURCES
src/CMAESMinimizer.cxx
DEPENDENCIES
MathCore
Hist
LIBRARIES
cmaes
)
128 changes: 128 additions & 0 deletions math/cmaes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
### This is support for black-box optimization with CMA-ES from within ROOT (http://root.cern.ch/).

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 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.

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.
Loading