diff --git a/.github/workflows/root-ci.yml b/.github/workflows/root-ci.yml index 540752428518f..d8d8297d96c8c 100644 --- a/.github/workflows/root-ci.yml +++ b/.github/workflows/root-ci.yml @@ -402,7 +402,7 @@ jobs: - image: alma9 is_special: true property: modules_off - overrides: ["runtime_cxxmodules=Off"] + overrides: ["runtime_cxxmodules=OFF", "minuit1=OFF"] - image: alma9 is_special: true property: march_native diff --git a/cmake/modules/RootBuildOptions.cmake b/cmake/modules/RootBuildOptions.cmake index 9add71c9aa9fc..952abc16b02cb 100644 --- a/cmake/modules/RootBuildOptions.cmake +++ b/cmake/modules/RootBuildOptions.cmake @@ -146,6 +146,7 @@ ROOT_BUILD_OPTION(llvm13_broken_tests OFF "Enable broken tests with LLVM 13 on W 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 OFF "Build libMathMore extended math library (requires GSL) [GPL]") ROOT_BUILD_OPTION(memory_termination OFF "Free internal ROOT memory before process termination (experimental, used for leak checking)") +ROOT_BUILD_OPTION(minuit1 ON "Build also the original C++ implementation of Minuit, alongside Minuit 2. This flag has no effect on Minuit 2, which is always built.") ROOT_BUILD_OPTION(minuit2_mpi OFF "Enable support for MPI in Minuit2") ROOT_BUILD_OPTION(minuit2_omp OFF "Enable support for OpenMP in Minuit2") ROOT_BUILD_OPTION(mpi OFF "Enable support for Message Passing Interface (MPI)") diff --git a/math/CMakeLists.txt b/math/CMakeLists.txt index fddecb1db1a1e..b02c6d97b6365 100644 --- a/math/CMakeLists.txt +++ b/math/CMakeLists.txt @@ -9,7 +9,9 @@ if(mathmore) add_subdirectory(mathmore) endif() add_subdirectory(matrix) -add_subdirectory(minuit) +if(minuit1) + add_subdirectory(minuit) +endif() add_subdirectory(minuit2) add_subdirectory(fumili) add_subdirectory(physics) diff --git a/roofit/roofitcore/CMakeLists.txt b/roofit/roofitcore/CMakeLists.txt index d6c956ab1e1a9..ade015dfffa69 100644 --- a/roofit/roofitcore/CMakeLists.txt +++ b/roofit/roofitcore/CMakeLists.txt @@ -492,6 +492,10 @@ if(fftw3) target_compile_definitions(RooFitCore PUBLIC ROOFIT_MATH_FFTW3) endif() +if(minuit1) + target_compile_definitions(RooFitCore PUBLIC ROOFIT_MINUIT_1) +endif() + target_include_directories(RooFitCore PUBLIC $) # The SMatrix package is header-only, but it's only exposed via the Smatrix diff --git a/roofit/roofitcore/inc/RooProdPdf.h b/roofit/roofitcore/inc/RooProdPdf.h index 627285f752e86..1d258d1341ed0 100644 --- a/roofit/roofitcore/inc/RooProdPdf.h +++ b/roofit/roofitcore/inc/RooProdPdf.h @@ -102,6 +102,10 @@ class RooProdPdf : public RooAbsPdf { std::unique_ptr compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext & ctx) const override; + std::unique_ptr compileToFixedProdPdf(RooArgSet const &normSet, RooArgSet const *intSet, + const char *rangeName, RooFit::Detail::CompileContext &ctx, + bool compileServers) const; + // The cache object. Internal, do not use. class CacheElem final : public RooAbsCacheElement { public: @@ -211,7 +215,8 @@ namespace RooFit::Detail { /// normalization set. class RooFixedProdPdf : public RooAbsPdf { public: - RooFixedProdPdf(std::unique_ptr &&prodPdf, RooArgSet const &normSet); + RooFixedProdPdf(std::unique_ptr &&prodPdf, RooArgSet const &normSet, RooArgSet const *intSet, + const char *rangeName); RooFixedProdPdf(const RooFixedProdPdf &other, const char *name = nullptr); inline TObject *clone(const char *newname) const override { return new RooFixedProdPdf(*this, newname); } @@ -269,10 +274,12 @@ class RooFixedProdPdf : public RooAbsPdf { private: double evaluate() const override; + RooArgSet _intSet; RooArgSet _normSet; RooSetProxy _servers; std::unique_ptr _prodPdf; bool _isRearranged = false; + std::string _rangeName; ClassDefOverride(RooFit::Detail::RooFixedProdPdf, 0); }; diff --git a/roofit/roofitcore/src/RooFit/Evaluator.cxx b/roofit/roofitcore/src/RooFit/Evaluator.cxx index 2cb6f4589df70..0ad61d2774a26 100644 --- a/roofit/roofitcore/src/RooFit/Evaluator.cxx +++ b/roofit/roofitcore/src/RooFit/Evaluator.cxx @@ -112,6 +112,7 @@ struct NodeInfo { bool isCategory = false; bool hasLogged = false; bool computeInGPU = false; + bool isValueServer = false; // if this node is a value server to the top node std::size_t outputSize = 1; std::size_t lastSetValCount = std::numeric_limits::max(); int lastCatVal = std::numeric_limits::max(); @@ -207,6 +208,16 @@ Evaluator::Evaluator(const RooAbsReal &absReal, bool useGPU) } } + // Figure out which nodes are value servers to the top node + _nodes.back().isValueServer = true; // the top node itself + for (auto iter = _nodes.rbegin(); iter != _nodes.rend(); ++iter) { + if (!iter->isValueServer) + continue; + for (auto &serverInfo : iter->serverInfos) { + serverInfo->isValueServer = true; + } + } + syncDataTokens(); if (_useGPU) { @@ -687,7 +698,7 @@ RooArgSet Evaluator::getParameters() const { RooArgSet parameters; for (auto &nodeInfo : _nodes) { - if (nodeInfo.absArg->isFundamental()) { + if (nodeInfo.isValueServer && nodeInfo.absArg->isFundamental()) { parameters.add(*nodeInfo.absArg); } } diff --git a/roofit/roofitcore/src/RooProdPdf.cxx b/roofit/roofitcore/src/RooProdPdf.cxx index e44f8cc621e1a..709bbdd8127d3 100644 --- a/roofit/roofitcore/src/RooProdPdf.cxx +++ b/roofit/roofitcore/src/RooProdPdf.cxx @@ -2147,34 +2147,53 @@ RooProdPdf::compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileC } } + return compileToFixedProdPdf(normSet, nullptr, nullptr, ctx, true); +} + +std::unique_ptr RooProdPdf::compileToFixedProdPdf(RooArgSet const &normSet, RooArgSet const *intSet, + const char *rangeName, RooFit::Detail::CompileContext &ctx, + bool compileServers) const +{ std::unique_ptr prodPdfClone{static_cast(this->Clone())}; ctx.markAsCompiled(*prodPdfClone); - for (const auto server : prodPdfClone->servers()) { - auto nsetForServer = fillNormSetForServer(normSet, *server); - RooArgSet const &nset = nsetForServer ? *nsetForServer : normSet; + if (compileServers) + for (const auto server : prodPdfClone->servers()) { + auto nsetForServer = fillNormSetForServer(normSet, *server); + RooArgSet const &nset = nsetForServer ? *nsetForServer : normSet; - RooArgSet depList; - server->getObservables(&nset, depList); + RooArgSet depList; + server->getObservables(&nset, depList); - ctx.compileServer(*server, *prodPdfClone, depList); - } + ctx.compileServer(*server, *prodPdfClone, depList); + } - auto fixedProdPdf = std::make_unique(std::move(prodPdfClone), normSet); - ctx.markAsCompiled(*fixedProdPdf); + auto fixedProdPdf = + std::make_unique(std::move(prodPdfClone), normSet, intSet, rangeName); + if (compileServers) + ctx.markAsCompiled(*fixedProdPdf); + else + ctx.compileServers(*fixedProdPdf, normSet); return fixedProdPdf; } namespace RooFit::Detail { -RooFixedProdPdf::RooFixedProdPdf(std::unique_ptr &&prodPdf, RooArgSet const &normSet) +RooFixedProdPdf::RooFixedProdPdf(std::unique_ptr &&prodPdf, RooArgSet const &normSet, + RooArgSet const *intSet, const char *rangeName) : RooAbsPdf(prodPdf->GetName(), prodPdf->GetTitle()), _normSet{normSet}, _servers("!servers", "List of servers", this), - _prodPdf{std::move(prodPdf)} + _prodPdf{std::move(prodPdf)}, + _rangeName{rangeName ? rangeName : ""} { - auto cache = _prodPdf->createCacheElem(&_normSet, nullptr); + if (intSet) { + _intSet.add(*intSet); + } + + RooArgSet const *iset = _intSet.empty() ? nullptr : &_intSet; + auto cache = _prodPdf->createCacheElem(&_normSet, iset, _rangeName.empty() ? nullptr : _rangeName.c_str()); _isRearranged = cache->_isRearranged; // The actual servers for a given normalization set depend on whether the @@ -2190,25 +2209,27 @@ RooFixedProdPdf::RooFixedProdPdf(std::unique_ptr &&prodPdf, RooArgSe // We don't want to carry the full cache object around, so we let it go out // of scope and transfer the ownership of the args that we actually need. cache->_ownedList.releaseOwnership(); - std::vector> owned; - for (RooAbsArg *arg : cache->_ownedList) { - owned.emplace_back(arg); - } + // std::vector> owned; + // for (RooAbsArg *arg : cache->_ownedList) { + // owned.emplace_back(arg); + //} for (RooAbsArg *arg : cache->_partList) { _servers.add(*arg); - auto found = std::find_if(owned.begin(), owned.end(), [&](auto const &ptr) { return arg == ptr.get(); }); - if (found != owned.end()) { - addOwnedComponents(std::move(owned[std::distance(owned.begin(), found)])); - } + // auto found = std::find_if(owned.begin(), owned.end(), [&](auto const &ptr) { return arg == ptr.get(); }); + // if (found != owned.end()) { + // addOwnedComponents(std::move(owned[std::distance(owned.begin(), found)])); + //} } } RooFixedProdPdf::RooFixedProdPdf(const RooFixedProdPdf &other, const char *name) : RooAbsPdf(other, name), + _intSet{other._intSet}, _normSet{other._normSet}, _servers("!servers", this, other._servers), _prodPdf{static_cast(other._prodPdf->Clone())}, - _isRearranged{other._isRearranged} + _isRearranged{other._isRearranged}, + _rangeName{other._rangeName} { } diff --git a/roofit/roofitcore/src/RooProjectedPdf.cxx b/roofit/roofitcore/src/RooProjectedPdf.cxx index 154d10461c370..f8b40c8564bbb 100644 --- a/roofit/roofitcore/src/RooProjectedPdf.cxx +++ b/roofit/roofitcore/src/RooProjectedPdf.cxx @@ -286,10 +286,9 @@ RooProjectedPdf::compileForNormSet(RooArgSet const &normSet, RooFit::Detail::Com auto newArgPdf = std::make_unique(namePdf.c_str(), namePdf.c_str(), *newArg); - ctx.markAsCompiled(*newArg); - ctx.markAsCompiled(*newArgPdf); + ctx.compileServers(*newArgPdf, normSet); - newArgPdf->addOwnedComponents(std::move(newArg)); + ctx.markAsCompiled(*newArgPdf); return newArgPdf; } diff --git a/roofit/roofitcore/src/RooRealIntegral.cxx b/roofit/roofitcore/src/RooRealIntegral.cxx index 22542d7720d7a..45e3e55d02460 100644 --- a/roofit/roofitcore/src/RooRealIntegral.cxx +++ b/roofit/roofitcore/src/RooRealIntegral.cxx @@ -40,6 +40,7 @@ integration is performed in the various implementations of the RooAbsIntegrator #include #include #include +#include #include #include #include @@ -1114,6 +1115,13 @@ Int_t RooRealIntegral::getCacheAllNumeric() std::unique_ptr RooRealIntegral::compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const { + if (auto *prodPdf = dynamic_cast(&*_function)) { + getVal(); + auto out = prodPdf->compileToFixedProdPdf(_funcNormSet ? *_funcNormSet : normSet, &_anaList, + RooNameReg::str(_rangeName), ctx, false); + out->SetName(GetName()); + return out; + } return RooAbsReal::compileForNormSet(_funcNormSet ? *_funcNormSet : normSet, ctx); } diff --git a/roofit/roofitcore/test/CMakeLists.txt b/roofit/roofitcore/test/CMakeLists.txt index 09d64af90f5ec..e52dc8a4b7568 100644 --- a/roofit/roofitcore/test/CMakeLists.txt +++ b/roofit/roofitcore/test/CMakeLists.txt @@ -90,6 +90,10 @@ if(mathmore) endif() configure_file(stressRooFit_ref.root stressRooFit_ref.root COPYONLY) +configure_file(stressRooFit_ref_minuit1.root stressRooFit_ref_minuit1.root COPYONLY) +if(minuit1) + ROOT_ADD_TEST(test-stressroofit-cpu-minuit1 COMMAND stressRooFit -minim Minuit -f stressRooFit_ref_minuit1.root -b cpu FAILREGEX "FAILED|Error in") +endif() if(roofit_legacy_eval_backend) ROOT_ADD_TEST(test-stressroofit-legacy COMMAND stressRooFit -b legacy FAILREGEX "FAILED|Error in") endif() diff --git a/roofit/roofitcore/test/stressRooFit.cxx b/roofit/roofitcore/test/stressRooFit.cxx index b3b7144ce1fd4..3eb77a7e96f18 100644 --- a/roofit/roofitcore/test/stressRooFit.cxx +++ b/roofit/roofitcore/test/stressRooFit.cxx @@ -255,7 +255,7 @@ int main(int argc, const char *argv[]) // string refFileName = "http://root.cern.ch/files/stressRooFit_v534_ref.root" ; string refFileName = "stressRooFit_ref.root"; - string minimizerName = "Minuit"; + string minimizerName = "Minuit2"; auto verbosityOptionErrorMsg = "Multiple verbosity-related options have been passed to stressRooFit! The options " "-v, -vv, and -q are mutually exclusive."; diff --git a/roofit/roofitcore/test/stressRooFit_ref.root b/roofit/roofitcore/test/stressRooFit_ref.root index dd99118d06673..c774d8830c544 100644 Binary files a/roofit/roofitcore/test/stressRooFit_ref.root and b/roofit/roofitcore/test/stressRooFit_ref.root differ diff --git a/roofit/roofitcore/test/stressRooFit_ref_minuit1.root b/roofit/roofitcore/test/stressRooFit_ref_minuit1.root new file mode 100644 index 0000000000000..dd99118d06673 Binary files /dev/null and b/roofit/roofitcore/test/stressRooFit_ref_minuit1.root differ diff --git a/roofit/roofitcore/test/testSumW2Error.cxx b/roofit/roofitcore/test/testSumW2Error.cxx index 1a6338996712d..e184494e0631b 100644 --- a/roofit/roofitcore/test/testSumW2Error.cxx +++ b/roofit/roofitcore/test/testSumW2Error.cxx @@ -49,26 +49,21 @@ TEST(SumW2Error, BatchMode) using namespace RooFit; - auto fit = [&](RooAbsData &data, bool sumw2, EvalBackend evalBackend, std::string const &minimizer, - int printLevel = -1) { + auto fit = [&](RooAbsData &data, bool sumw2, EvalBackend evalBackend, int printLevel = -1) { params.assign(initialParams); - return std::unique_ptr{model.fitTo(data, Save(), SumW2Error(sumw2), Strategy(1), evalBackend, - Minimizer(minimizer.c_str()), PrintLevel(printLevel))}; + return std::unique_ptr{ + model.fitTo(data, Save(), SumW2Error(sumw2), Strategy(1), evalBackend, PrintLevel(printLevel))}; }; auto scalar = EvalBackend::Legacy(); auto batchMode = EvalBackend::Cpu(); // Compare batch mode vs. scalar mode for non-SumW2 fits on UNWEIGHTED datasets - EXPECT_TRUE(fit(*dataSet, 0, scalar, "Minuit")->isIdentical(*fit(*dataSet, 0, batchMode, "Minuit"))) - << " different results for Minuit fit to RooDataSet without SumW2Error correction."; - EXPECT_TRUE(fit(*dataHist, 0, scalar, "Minuit")->isIdentical(*fit(*dataHist, 0, batchMode, "Minuit"))) - << " different results for Minuit fit to RooDataHist without SumW2Error correction."; - EXPECT_TRUE(fit(*dataSet, 0, scalar, "Minuit2")->isIdentical(*fit(*dataSet, 0, batchMode, "Minuit2"))) - << " different results for Minuit2 fit to RooDataSet without SumW2Error correction."; - EXPECT_TRUE(fit(*dataHist, 0, scalar, "Minuit2")->isIdentical(*fit(*dataHist, 0, batchMode, "Minuit2"))) - << " different results for Minuit2 fit to RooDataHist without SumW2Error correction."; + EXPECT_TRUE(fit(*dataSet, 0, scalar)->isIdentical(*fit(*dataSet, 0, batchMode))) + << " different results for fit to RooDataSet without SumW2Error correction."; + EXPECT_TRUE(fit(*dataHist, 0, scalar)->isIdentical(*fit(*dataHist, 0, batchMode))) + << " different results for fit to RooDataHist without SumW2Error correction."; // We can't compare the covariance matrix in these next cases, because it is // externally provided. Still, it's okay because the parameter values and @@ -76,28 +71,16 @@ TEST(SumW2Error, BatchMode) // covariance matrix. // Compare batch mode vs. scalar mode for SumW2 fits on UNWEIGHTED datasets - EXPECT_TRUE(fit(*dataSet, 1, scalar, "Minuit")->isIdenticalNoCov(*fit(*dataSet, 1, batchMode, "Minuit"))) - << " different results for Minuit fit to RooDataSet with SumW2Error correction."; - EXPECT_TRUE(fit(*dataHist, 1, scalar, "Minuit")->isIdenticalNoCov(*fit(*dataHist, 1, batchMode, "Minuit"))) - << " different results for Minuit fit to RooDataHist with SumW2Error correction."; - EXPECT_TRUE(fit(*dataSet, 1, scalar, "Minuit2")->isIdenticalNoCov(*fit(*dataSet, 1, batchMode, "Minuit2"))) - << " different results for Minuit2 fit to RooDataSet with SumW2Error correction."; - EXPECT_TRUE(fit(*dataHist, 1, scalar, "Minuit2")->isIdenticalNoCov(*fit(*dataHist, 1, batchMode, "Minuit2"))) - << " different results for Minuit2 fit to RooDataHist with SumW2Error correction."; + EXPECT_TRUE(fit(*dataSet, 1, scalar)->isIdenticalNoCov(*fit(*dataSet, 1, batchMode))) + << " different results for fit to RooDataSet with SumW2Error correction."; + EXPECT_TRUE(fit(*dataHist, 1, scalar)->isIdenticalNoCov(*fit(*dataHist, 1, batchMode))) + << " different results for fit to RooDataHist with SumW2Error correction."; // Compare batch mode vs. scalar mode for SumW2 fits on WEIGHTED datasets - EXPECT_TRUE( - fit(dataSetWeighted, 1, scalar, "Minuit")->isIdenticalNoCov(*fit(dataSetWeighted, 1, batchMode, "Minuit"))) - << " different results for Minuit fit to weighted RooDataSet with SumW2Error correction."; - EXPECT_TRUE( - fit(*dataHistWeighted, 1, scalar, "Minuit")->isIdenticalNoCov(*fit(*dataHistWeighted, 1, batchMode, "Minuit"))) - << " different results for Minuit fit to weighted RooDataHist with SumW2Error correction."; - EXPECT_TRUE( - fit(dataSetWeighted, 1, scalar, "Minuit2")->isIdenticalNoCov(*fit(dataSetWeighted, 1, batchMode, "Minuit2"))) - << " different results for Minuit2 fit to weighted RooDataSet with SumW2Error correction."; - EXPECT_TRUE( - fit(*dataHistWeighted, 1, scalar, "Minuit2")->isIdenticalNoCov(*fit(*dataHistWeighted, 1, batchMode, "Minuit2"))) - << " different results for Minuit2 fit to weighted RooDataHist with SumW2Error correction."; + EXPECT_TRUE(fit(dataSetWeighted, 1, scalar)->isIdenticalNoCov(*fit(dataSetWeighted, 1, batchMode))) + << " different results for fit to weighted RooDataSet with SumW2Error correction."; + EXPECT_TRUE(fit(*dataHistWeighted, 1, scalar)->isIdenticalNoCov(*fit(*dataHistWeighted, 1, batchMode))) + << " different results for fit to weighted RooDataHist with SumW2Error correction."; } TEST(SumW2Error, ExtendedFit) @@ -128,11 +111,8 @@ TEST(SumW2Error, ExtendedFit) auto *wFunc = ws.factory("w[1.5]"); auto *w = dataNoWeights->addColumn(*wFunc); - RooDataSet data{dataNoWeights->GetName(), - dataNoWeights->GetTitle(), - *dataNoWeights->get(), - RooFit::Import(*dataNoWeights), - RooFit::WeightVar(w->GetName())}; + RooDataSet data{dataNoWeights->GetName(), dataNoWeights->GetTitle(), *dataNoWeights->get(), + RooFit::Import(*dataNoWeights), RooFit::WeightVar(w->GetName())}; RooDataHist datahist{"datahist", "datahist", *data.get(), data}; RooArgSet params; @@ -143,9 +123,8 @@ TEST(SumW2Error, ExtendedFit) auto doFit = [&](RooFit::EvalBackend evalBackend, bool sumW2Error, const char *range) { params.assign(initialParams); - return std::unique_ptr{shp->fitTo(datahist, Extended(), Range(range), Save(), - SumW2Error(sumW2Error), Strategy(1), PrintLevel(-1), evalBackend, - Minimizer("Minuit2", "migrad"))}; + return std::unique_ptr{shp->fitTo( + datahist, Extended(), Range(range), Save(), SumW2Error(sumW2Error), Strategy(1), PrintLevel(-1), evalBackend)}; }; // compare batch mode and scalar mode fit results for full range diff --git a/roofit/roostats/CMakeLists.txt b/roofit/roostats/CMakeLists.txt index 6d81e76646138..f2342b8fb2e3a 100644 --- a/roofit/roostats/CMakeLists.txt +++ b/roofit/roostats/CMakeLists.txt @@ -9,6 +9,10 @@ # @author Pere Mato, CERN ############################################################################ +if(minuit1) + list(APPEND EXTRA_LIBRARIES Minuit) +endif() + set (EXTRA_DICT_OPTS) if (runtime_cxxmodules AND WIN32) set (EXTRA_DICT_OPTS NO_CXXMODULE) @@ -121,6 +125,8 @@ ROOT_STANDARD_LIBRARY_PACKAGE(RooStats src/UpperLimitMCSModule.cxx DICTIONARY_OPTIONS "-writeEmptyRootPCM" + LIBRARIES + ${EXTRA_LIBRARIES} DEPENDENCIES Core RooFit @@ -130,7 +136,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(RooStats Hist Matrix MathCore - Minuit Foam Graf Gpad diff --git a/roofit/roostats/src/LikelihoodInterval.cxx b/roofit/roostats/src/LikelihoodInterval.cxx index c30aa78682e7c..b02e47fa1b115 100644 --- a/roofit/roostats/src/LikelihoodInterval.cxx +++ b/roofit/roostats/src/LikelihoodInterval.cxx @@ -58,7 +58,9 @@ #include "RooFunctor.h" #include "RooProfileLL.h" +#ifdef ROOFIT_MINUIT_1 #include "TMinuitMinimizer.h" +#endif #include #include @@ -260,8 +262,10 @@ bool LikelihoodInterval::CreateMinimizer() { ccoutE(InputArguments) << minimType << " is wrong type of minimizer for getting interval limits or contours - must use Minuit or Minuit2" << std::endl; return false; } +#ifdef ROOFIT_MINUIT_1 // do not use static instance of TMInuit which could interfere with RooFit if (minimType == "Minuit") TMinuitMinimizer::UseStaticMinuit(false); +#endif // create minimizer class fMinimizer = std::shared_ptr(ROOT::Math::Factory::CreateMinimizer(minimType, "Migrad")); diff --git a/roofit/roostats/test/CMakeLists.txt b/roofit/roostats/test/CMakeLists.txt index 75eff086a88d6..5193ead7d6738 100644 --- a/roofit/roostats/test/CMakeLists.txt +++ b/roofit/roostats/test/CMakeLists.txt @@ -11,14 +11,16 @@ if(mathmore) endif() configure_file(stressRooStats_ref.root stressRooStats_ref.root COPYONLY) -if(roofit_legacy_eval_backend) - ROOT_ADD_TEST(test-stressroostats-legacy COMMAND stressRooStats -b legacy FAILREGEX "FAILED|Error in" LABELS longtest) +if(minuit1) + if(roofit_legacy_eval_backend) + ROOT_ADD_TEST(test-stressroostats-legacy-minuit1 COMMAND stressRooStats -minim Minuit -b legacy FAILREGEX "FAILED|Error in" LABELS longtest) + endif() + ROOT_ADD_TEST(test-stressroostats-cpu-minuit1 COMMAND stressRooStats -minim Minuit -b cpu FAILREGEX "FAILED|Error in" LABELS longtest) endif() -ROOT_ADD_TEST(test-stressroostats-cpu COMMAND stressRooStats -b cpu FAILREGEX "FAILED|Error in" LABELS longtest) if(cuda) ROOT_ADD_TEST(test-stressroostats-cuda COMMAND stressRooStats -b cuda FAILREGEX "FAILED|Error in" LABELS longtest RESOURCE_LOCK GPU) endif() if(roofit_legacy_eval_backend) - ROOT_ADD_TEST(test-stressroostats-legacy-minuit2 COMMAND stressRooStats -minim Minuit2 -b legacy FAILREGEX "FAILED|Error in" LABELS longtest) + ROOT_ADD_TEST(test-stressroostats-legacy COMMAND stressRooStats -b legacy FAILREGEX "FAILED|Error in" LABELS longtest) endif() -ROOT_ADD_TEST(test-stressroostats-cpu-minuit2 COMMAND stressRooStats -minim Minuit2 -b cpu FAILREGEX "FAILED|Error in" LABELS longtest) +ROOT_ADD_TEST(test-stressroostats-cpu COMMAND stressRooStats -b cpu FAILREGEX "FAILED|Error in" LABELS longtest) diff --git a/roofit/roostats/test/stressRooStats.cxx b/roofit/roostats/test/stressRooStats.cxx index 98a1267ce9d5a..afd18144a24d2 100644 --- a/roofit/roostats/test/stressRooStats.cxx +++ b/roofit/roostats/test/stressRooStats.cxx @@ -313,7 +313,7 @@ int main(int argc, const char *argv[]) // string refFileName = "http://root.cern/files/stressRooStats_v534_ref.root" ; string refFileName = "stressRooStats_ref.root"; - string minimizerName = "Minuit"; + string minimizerName = "Minuit2"; // Parse command line arguments for (int i = 1; i < argc; i++) { diff --git a/tmva/tmva/CMakeLists.txt b/tmva/tmva/CMakeLists.txt index c15e2dc980b9d..13b3faa2c0479 100644 --- a/tmva/tmva/CMakeLists.txt +++ b/tmva/tmva/CMakeLists.txt @@ -9,6 +9,20 @@ # @author Pere Mato, CERN ############################################################################ +if(minuit1) + set(TMVA_EXTRA_HEADERS + TMVA/MinuitFitter.h + TMVA/MinuitWrapper.h + ) + set(TMVA_EXTRA_SOURCES + src/MinuitFitter.cxx + src/MinuitWrapper.cxx + ) + set(TMVA_EXTRA_DEPENDENCIES + Minuit + ) +endif() + if(NOT tmva-gpu) set(installoptions ${installoptions} FILTER "Cuda") endif() @@ -99,8 +113,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(TMVA TMVA/MethodRuleFit.h TMVA/MethodSVM.h TMVA/MethodTMlpANN.h - TMVA/MinuitFitter.h - TMVA/MinuitWrapper.h TMVA/MisClassificationError.h TMVA/ModulekNN.h TMVA/Monitoring.h @@ -288,8 +300,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(TMVA src/MethodRuleFit.cxx src/MethodSVM.cxx src/MethodTMlpANN.cxx - src/MinuitFitter.cxx - src/MinuitWrapper.cxx src/MisClassificationError.cxx src/ModulekNN.cxx src/MsgLogger.cxx @@ -386,7 +396,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(TMVA Tree Hist Matrix - Minuit MLP MathCore Core @@ -400,6 +409,10 @@ ROOT_STANDARD_LIBRARY_PACKAGE(TMVA ${EXTRA_DICT_OPTS} ) +if(minuit1) + target_compile_definitions(TMVA PRIVATE TMVA_MINUIT_1) +endif() + if(MSVC) target_compile_definitions(TMVA PRIVATE _USE_MATH_DEFINES) endif() diff --git a/tmva/tmva/src/MethodCuts.cxx b/tmva/tmva/src/MethodCuts.cxx index 9c2614fa0dffe..e5275c1ee5bae 100644 --- a/tmva/tmva/src/MethodCuts.cxx +++ b/tmva/tmva/src/MethodCuts.cxx @@ -91,7 +91,9 @@ #include "TMVA/MCFitter.h" #include "TMVA/MethodBase.h" #include "TMVA/MethodFDA.h" +#ifdef TMVA_MINUIT_1 #include "TMVA/MinuitFitter.h" +#endif #include "TMVA/MsgLogger.h" #include "TMVA/PDF.h" #include "TMVA/Results.h" @@ -674,7 +676,11 @@ void TMVA::MethodCuts::Train( void ) fitter = new MCFitter ( *this, TString::Format("%sFitter_MC", GetName()), ranges, GetOptions() ); break; case kUseMinuit: +#ifdef TMVA_MINUIT_1 fitter = new MinuitFitter ( *this, TString::Format("%sFitter_MINUIT", GetName()), ranges, GetOptions() ); +#else + Log() << kFATAL << "Can't use MINUIT fitter because ROOT was build without MINUIT 1" << Endl; +#endif break; case kUseSimulatedAnnealing: fitter = new SimulatedAnnealingFitter( *this, TString::Format("%sFitter_SA", GetName()), ranges, GetOptions() ); diff --git a/tmva/tmva/src/MethodFDA.cxx b/tmva/tmva/src/MethodFDA.cxx index f57025f557526..4e16fb5b1e546 100644 --- a/tmva/tmva/src/MethodFDA.cxx +++ b/tmva/tmva/src/MethodFDA.cxx @@ -53,7 +53,9 @@ Can compute regression value for one dimensional output #include "TMVA/IMethod.h" #include "TMVA/MCFitter.h" #include "TMVA/MethodBase.h" +#ifdef TMVA_MINUIT_1 #include "TMVA/MinuitFitter.h" +#endif #include "TMVA/MsgLogger.h" #include "TMVA/Timer.h" #include "TMVA/Tools.h" @@ -300,8 +302,12 @@ void TMVA::MethodFDA::ProcessOptions() // create minimiser fConvergerFitter = (IFitterTarget*)this; if (fConverger == "MINUIT") { +#ifdef TMVA_MINUIT_1 fConvergerFitter = new MinuitFitter( *this, TString::Format("%s_Converger_Minuit", GetName()), fParRange, GetOptions() ); SetOptions(dynamic_cast(fConvergerFitter)->GetOptions()); +#else + Log() << kFATAL << "Can't use MINUIT converger because ROOT was build without MINUIT 1" << Endl; +#endif } if(fFitMethod == "MC") @@ -310,9 +316,13 @@ void TMVA::MethodFDA::ProcessOptions() fFitter = new GeneticFitter( *fConvergerFitter, TString::Format("%s_Fitter_GA", GetName()), fParRange, GetOptions() ); else if (fFitMethod == "SA") fFitter = new SimulatedAnnealingFitter( *fConvergerFitter, TString::Format("%s_Fitter_SA", GetName()), fParRange, GetOptions() ); - else if (fFitMethod == "MINUIT") + else if (fFitMethod == "MINUIT") { +#ifdef TMVA_MINUIT_1 fFitter = new MinuitFitter( *fConvergerFitter, TString::Format("%s_Fitter_Minuit", GetName()), fParRange, GetOptions() ); - else { +#else + Log() << kFATAL << "Can't use MINUIT fitter because ROOT was build without MINUIT 1" << Endl; +#endif + } else { Log() << kFATAL << " Do not understand fit method:" << fFitMethod << Endl; } diff --git a/tmva/tmva/src/MethodMLP.cxx b/tmva/tmva/src/MethodMLP.cxx index 20f908e437a0e..98813f3a140d6 100644 --- a/tmva/tmva/src/MethodMLP.cxx +++ b/tmva/tmva/src/MethodMLP.cxx @@ -65,7 +65,9 @@ Multilayer Perceptron class built off of MethodANNBase #include "TH1.h" #include "TString.h" +#ifdef MethodMLP_UseMinuit__ #include "TFitter.h" +#endif #include "TMatrixD.h" #include "TMath.h" diff --git a/tmva/tmva/src/OptimizeConfigParameters.cxx b/tmva/tmva/src/OptimizeConfigParameters.cxx index 6d840e1979524..fb166a0174636 100644 --- a/tmva/tmva/src/OptimizeConfigParameters.cxx +++ b/tmva/tmva/src/OptimizeConfigParameters.cxx @@ -38,7 +38,9 @@ #include "TMVA/MethodBase.h" #include "TMVA/MethodFDA.h" #include "TMVA/MsgLogger.h" +#ifdef TMVA_MINUIT_1 #include "TMVA/MinuitFitter.h" +#endif #include "TMVA/PDF.h" #include "TMVA/Tools.h" #include "TMVA/Types.h" @@ -263,9 +265,13 @@ void TMVA::OptimizeConfigParameters::optimizeFit() TString opt="FitStrategy=0:UseImprove=False:UseMinos=False:Tolerance=100"; if (!TMVA::gConfig().IsSilent() ) opt += TString(":PrintLevel=0"); +#ifdef TMVA_MINUIT_1 fitter = new MinuitFitter( *this, "FitterMinuit_BDTOptimize", ranges, opt ); +#else + Log() << kFATAL << "Can't use MINUIT optimizer because ROOT was build without MINUIT 1" << Endl; +#endif }else if ( fOptimizationFitType == "FitGA" ) { TString opt="PopSize=20:Steps=30:Cycles=3:ConvCrit=0.01:SaveBestCycle=5"; fitter = new GeneticFitter( *this,