Binding detailed example: Minuit2#

Let’s try a non-trivial example: Minuit2 (6.26.10 standalone edition)

Expectations#

  • Be able to minimize a very simple function and get some parameters

import sys

Step 1: Get source#

  • Download Minuit2 source (already provided in minuit2)

Step 2: Plan interface#

  • You should know what the C++ looks like, and know what you want the Python to look like

  • For now, let’s replicate the C++ experience

For example: a simple minimizer for \(f(x) = x^2\) (should quickly find 0 as minimum):

  • Define FCN

  • Setup parameters

  • Minimize

  • Print result

Will use print out for illustration (instead of MnPrint::SetLevel)

%%writefile SimpleFCN.h
#pragma once

#include <Minuit2/FCNBase.h>
#include <Minuit2/FunctionMinimum.h>
#include <Minuit2/MnPrint.h>
#include <Minuit2/MnMigrad.h>

#include <iostream>

using namespace ROOT::Minuit2;

class SimpleFCN : public FCNBase {
    // Always 0.5 for these sorts of fits
    
    double Up() const override {return 0.5;}
    
    // This computes whatever you are going to minimize
    double operator()(const std::vector<double> &v) const override {
        std::cout << "val = " << v.at(0) << std::endl;
        return v.at(0)*v.at(0);
    }
};
Writing SimpleFCN.h
%%writefile simpleminuit.cpp
#include "SimpleFCN.h"

int main() {
    SimpleFCN fcn;
    MnUserParameters upar;
    upar.Add("x", 1., 0.1);
    MnMigrad migrad(fcn, upar);
    FunctionMinimum min = migrad();
    std::cout << min << std::endl;
}
Writing simpleminuit.cpp
%%writefile CMakeLists.txt

cmake_minimum_required(VERSION 3.18...3.29)
project(Minuit2SimpleExamle LANGUAGES CXX)

include(FetchContent)
FetchContent_Declare(
  minuit2
  URL           https://github.com/root-project/root/archive/refs/tags/v6-26-10.tar.gz
  URL_HASH      SHA256=a84ed095252614c6e2084987fce9ce4a5a62057bfd5a4a2725123ca9f60f674f
  SOURCE_SUBDIR math/minuit2
  DOWNLOAD_NO_PROGRESS
)
FetchContent_MakeAvailable(minuit2)

add_executable(simpleminuit simpleminuit.cpp SimpleFCN.h)
target_link_libraries(simpleminuit PRIVATE Minuit2::Minuit2)
Writing CMakeLists.txt

Standard CMake configure and build (using Ninja instead of Make for speed)

!cmake -GNinja -S . -B build
!cmake --build build
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Deprecation Warning at build/_deps/minuit2-src/math/minuit2/CMakeLists.txt:7 (cmake_minimum_required):
  Compatibility with CMake < 3.5 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.


CMake Deprecation Warning at build/_deps/minuit2-src/math/minuit2/StandAlone.cmake:1 (cmake_minimum_required):
  Compatibility with CMake < 3.5 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.
Call Stack (most recent call first):
  build/_deps/minuit2-src/math/minuit2/CMakeLists.txt:250 (include)


-- Configuring done (18.7s)
-- Generating done (0.0s)
-- Build files have been written to: /home/runner/work/se-for-sci/se-for-sci/content/week12/03-pybind/build
[0/80] Building CXX object _deps/minui..._/__/mathcore/src/GenAlgoOptions.cxx.o
[0/80] Building CXX object _deps/minui...__/mathcore/src/MinimizerOptions.cxx.o
[0/80] Building CXX object _deps/minui...dir/AnalyticalGradientCalculator.cxx.o
[0/80] Building CXX object _deps/minui...les/Minuit2.dir/BFGSErrorUpdator.cxx.o
[0/80] Building CXX object _deps/minui...nuit2.dir/CombinedMinimumBuilder.cxx.o
[0/80] Building CXX object _deps/minui.../Minuit2.dir/DavidonErrorUpdator.cxx.o
[1/80] Building CXX object _deps/minui...les/Minuit2.dir/BFGSErrorUpdator.cxx.o
[1/80] Building CXX object _deps/minui...ternalInternalGradientCalculator.cxx.o
[2/80] Building CXX object _deps/minui.../Minuit2.dir/DavidonErrorUpdator.cxx.o
[2/80] Building CXX object _deps/minui...eFiles/Minuit2.dir/FumiliBuilder.cxx.o
[3/80] Building CXX object _deps/minui...__/mathcore/src/MinimizerOptions.cxx.o
[3/80] Building CXX object _deps/minui...s/Minuit2.dir/FumiliErrorUpdator.cxx.o
[4/80] Building CXX object _deps/minui...dir/AnalyticalGradientCalculator.cxx.o
[4/80] Building CXX object _deps/minui...it2.dir/FumiliGradientCalculator.cxx.o
[5/80] Building CXX object _deps/minui..._/__/mathcore/src/GenAlgoOptions.cxx.o
[5/80] Building CXX object _deps/minui...iles/Minuit2.dir/FumiliMinimizer.cxx.o
[6/80] Building CXX object _deps/minui...nuit2.dir/CombinedMinimumBuilder.cxx.o
[6/80] Building CXX object _deps/minui...inuit2.dir/FumiliStandardChi2FCN.cxx.o
[7/80] Building CXX object _deps/minui...ternalInternalGradientCalculator.cxx.o
[7/80] Building CXX object _deps/minui...miliStandardMaximumLikelihoodFCN.cxx.o
[8/80] Building CXX object _deps/minui...inuit2.dir/FumiliStandardChi2FCN.cxx.o
[8/80] Building CXX object _deps/minui...t2.dir/HessianGradientCalculator.cxx.o
[9/80] Building CXX object _deps/minui...s/Minuit2.dir/FumiliErrorUpdator.cxx.o
[9/80] Building CXX object _deps/minui...t2.dir/InitialGradientCalculator.cxx.o
[10/80] Building CXX object _deps/minu...it2.dir/FumiliGradientCalculator.cxx.o
[10/80] Building CXX object _deps/minu...eFiles/Minuit2.dir/LaEigenValues.cxx.o
[11/80] Building CXX object _deps/minu...iles/Minuit2.dir/FumiliMinimizer.cxx.o
[11/80] Building CXX object _deps/minu...Files/Minuit2.dir/LaInnerProduct.cxx.o
[12/80] Building CXX object _deps/minu...eFiles/Minuit2.dir/LaEigenValues.cxx.o
[12/80] Building CXX object _deps/minu...CMakeFiles/Minuit2.dir/LaInverse.cxx.o
[13/80] Building CXX object _deps/minu...eFiles/Minuit2.dir/FumiliBuilder.cxx.o
[13/80] Building CXX object _deps/minu...Files/Minuit2.dir/LaOuterProduct.cxx.o
[14/80] Building CXX object _deps/minu...Files/Minuit2.dir/LaInnerProduct.cxx.o
[14/80] Building CXX object _deps/minu...iles/Minuit2.dir/LaSumOfElements.cxx.o
[15/80] Building CXX object _deps/minu...miliStandardMaximumLikelihoodFCN.cxx.o
[15/80] Building CXX object _deps/minu...les/Minuit2.dir/LaVtMVSimilarity.cxx.o
[16/80] Building CXX object _deps/minu...CMakeFiles/Minuit2.dir/LaInverse.cxx.o
[16/80] Building CXX object _deps/minu...MakeFiles/Minuit2.dir/MPIProcess.cxx.o
[17/80] Building CXX object _deps/minu...iles/Minuit2.dir/LaSumOfElements.cxx.o
[17/80] Building CXX object _deps/minu...Files/Minuit2.dir/MinimumBuilder.cxx.o
[18/80] Building CXX object _deps/minu...les/Minuit2.dir/LaVtMVSimilarity.cxx.o
[18/80] Building CXX object _deps/minu...les/Minuit2.dir/Minuit2Minimizer.cxx.o
[19/80] Building CXX object _deps/minu...Files/Minuit2.dir/LaOuterProduct.cxx.o
[19/80] Building CXX object _deps/minu...eFiles/Minuit2.dir/MnApplication.cxx.o
[20/80] Building CXX object _deps/minu...t2.dir/HessianGradientCalculator.cxx.o
[20/80] Building CXX object _deps/minu...MakeFiles/Minuit2.dir/MnContours.cxx.o
[21/80] Building CXX object _deps/minu...t2.dir/InitialGradientCalculator.cxx.o
[21/80] Building CXX object _deps/minu.../Minuit2.dir/MnCovarianceSqueeze.cxx.o
[22/80] Building CXX object _deps/minu...MakeFiles/Minuit2.dir/MPIProcess.cxx.o
[22/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/MnEigen.cxx.o
[23/80] Building CXX object _deps/minu...Files/Minuit2.dir/MinimumBuilder.cxx.o
[23/80] Building CXX object _deps/minu...src/CMakeFiles/Minuit2.dir/MnFcn.cxx.o
[24/80] Building CXX object _deps/minu...src/CMakeFiles/Minuit2.dir/MnFcn.cxx.o
[24/80] Building CXX object _deps/minu...les/Minuit2.dir/MnFumiliMinimize.cxx.o
[25/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/MnEigen.cxx.o
[25/80] Building CXX object _deps/minu...iles/Minuit2.dir/MnFunctionCross.cxx.o
[26/80] Building CXX object _deps/minu.../Minuit2.dir/MnCovarianceSqueeze.cxx.o
[26/80] Building CXX object _deps/minu...it2.dir/MnGlobalCorrelationCoeff.cxx.o
[27/80] Building CXX object _deps/minu...eFiles/Minuit2.dir/MnApplication.cxx.o
[27/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/MnHesse.cxx.o
[28/80] Building CXX object _deps/minu...MakeFiles/Minuit2.dir/MnContours.cxx.o
[28/80] Building CXX object _deps/minu...keFiles/Minuit2.dir/MnLineSearch.cxx.o
[29/80] Building CXX object _deps/minu...it2.dir/MnGlobalCorrelationCoeff.cxx.o
[29/80] Building CXX object _deps/minu...s/Minuit2.dir/MnMachinePrecision.cxx.o
[30/80] Building CXX object _deps/minu...les/Minuit2.dir/MnFumiliMinimize.cxx.o
[30/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/MnMinos.cxx.o
[31/80] Building CXX object _deps/minu...s/Minuit2.dir/MnMachinePrecision.cxx.o
[31/80] Building CXX object _deps/minu...es/Minuit2.dir/MnParabolaFactory.cxx.o
[32/80] Building CXX object _deps/minu...les/Minuit2.dir/Minuit2Minimizer.cxx.o
[32/80] Building CXX object _deps/minu...iles/Minuit2.dir/MnParameterScan.cxx.o
[33/80] Building CXX object _deps/minu...es/Minuit2.dir/MnParabolaFactory.cxx.o
[33/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/MnPlot.cxx.o
[34/80] Building CXX object _deps/minu...keFiles/Minuit2.dir/MnLineSearch.cxx.o
[34/80] Building CXX object _deps/minu.../CMakeFiles/Minuit2.dir/MnPosDef.cxx.o
[35/80] Building CXX object _deps/minu...iles/Minuit2.dir/MnFunctionCross.cxx.o
[35/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/MnPrint.cxx.o
[36/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/MnPlot.cxx.o
[36/80] Building CXX object _deps/minu...akeFiles/Minuit2.dir/MnPrintImpl.cxx.o
[37/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/MnHesse.cxx.o
[37/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/MnScan.cxx.o
[38/80] Building CXX object _deps/minu...akeFiles/Minuit2.dir/MnPrintImpl.cxx.o
[38/80] Building CXX object _deps/minu...iles/Minuit2.dir/MnSeedGenerator.cxx.o
[39/80] Building CXX object _deps/minu...iles/Minuit2.dir/MnParameterScan.cxx.o
[39/80] Building CXX object _deps/minu...MakeFiles/Minuit2.dir/MnStrategy.cxx.o
[40/80] Building CXX object _deps/minu...MakeFiles/Minuit2.dir/MnStrategy.cxx.o
[40/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/MnTiny.cxx.o
[41/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/MnTiny.cxx.o
[41/80] Building CXX object _deps/minu...eFiles/Minuit2.dir/MnTraceObject.cxx.o
[42/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/MnMinos.cxx.o
[42/80] Building CXX object _deps/minu...CMakeFiles/Minuit2.dir/MnUserFcn.cxx.o
[43/80] Building CXX object _deps/minu.../CMakeFiles/Minuit2.dir/MnPosDef.cxx.o
[43/80] Building CXX object _deps/minu...Minuit2.dir/MnUserParameterState.cxx.o
[44/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/MnScan.cxx.o
[44/80] Building CXX object _deps/minu...les/Minuit2.dir/MnUserParameters.cxx.o
[45/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/MnPrint.cxx.o
[45/80] Building CXX object _deps/minu...Minuit2.dir/MnUserTransformation.cxx.o
[46/80] Building CXX object _deps/minu...iles/Minuit2.dir/MnSeedGenerator.cxx.o
[46/80] Building CXX object _deps/minu...it2.dir/ModularFunctionMinimizer.cxx.o
[47/80] Building CXX object _deps/minu...CMakeFiles/Minuit2.dir/MnUserFcn.cxx.o
[47/80] Building CXX object _deps/minu...Minuit2.dir/NegativeG2LineSearch.cxx.o
[48/80] Building CXX object _deps/minu...eFiles/Minuit2.dir/MnTraceObject.cxx.o
[48/80] Building CXX object _deps/minu...ir/Numerical2PGradientCalculator.cxx.o
[49/80] Building CXX object _deps/minu...les/Minuit2.dir/MnUserParameters.cxx.o
[49/80] Building CXX object _deps/minu...s/Minuit2.dir/ParametricFunction.cxx.o
[50/80] Building CXX object _deps/minu...Minuit2.dir/MnUserParameterState.cxx.o
[50/80] Building CXX object _deps/minu...akeFiles/Minuit2.dir/ScanBuilder.cxx.o
[51/80] Building CXX object _deps/minu...Minuit2.dir/NegativeG2LineSearch.cxx.o
[51/80] Building CXX object _deps/minu...Files/Minuit2.dir/SimplexBuilder.cxx.o
[52/80] Building CXX object _deps/minu...Minuit2.dir/MnUserTransformation.cxx.o
[52/80] Building CXX object _deps/minu...es/Minuit2.dir/SimplexParameters.cxx.o
[53/80] Building CXX object _deps/minu...it2.dir/ModularFunctionMinimizer.cxx.o
[53/80] Building CXX object _deps/minu...Minuit2.dir/SimplexSeedGenerator.cxx.o
[54/80] Building CXX object _deps/minu...s/Minuit2.dir/ParametricFunction.cxx.o
[54/80] Building CXX object _deps/minu...2.dir/SinParameterTransformation.cxx.o
[55/80] Building CXX object _deps/minu...ir/Numerical2PGradientCalculator.cxx.o
[55/80] Building CXX object _deps/minu...r/SqrtLowParameterTransformation.cxx.o
[56/80] Building CXX object _deps/minu...2.dir/SinParameterTransformation.cxx.o
[56/80] Building CXX object _deps/minu...ir/SqrtUpParameterTransformation.cxx.o
[57/80] Building CXX object _deps/minu...r/SqrtLowParameterTransformation.cxx.o
[57/80] Building CXX object _deps/minu...inuit2.dir/VariableMetricBuilder.cxx.o
[58/80] Building CXX object _deps/minu...es/Minuit2.dir/SimplexParameters.cxx.o
[58/80] Building CXX object _deps/minu...2.dir/VariableMetricEDMEstimator.cxx.o
[59/80] Building CXX object _deps/minu...ir/SqrtUpParameterTransformation.cxx.o
[59/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/mnbins.cxx.o
[60/80] Building CXX object _deps/minu...akeFiles/Minuit2.dir/ScanBuilder.cxx.o
[60/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mndasum.cxx.o
[61/80] Building CXX object _deps/minu...2.dir/VariableMetricEDMEstimator.cxx.o
[61/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mndaxpy.cxx.o
[62/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/mnbins.cxx.o
[62/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/mnddot.cxx.o
[63/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mndaxpy.cxx.o
[63/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mndscal.cxx.o
[64/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/mnddot.cxx.o
[64/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mndspmv.cxx.o
[65/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mndscal.cxx.o
[65/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/mndspr.cxx.o
[66/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mndspmv.cxx.o
[66/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mnlsame.cxx.o
[67/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/mndspr.cxx.o
[67/80] Building CXX object _deps/minu.../CMakeFiles/Minuit2.dir/mnteigen.cxx.o
[68/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mnlsame.cxx.o
[68/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mntplot.cxx.o
[69/80] Building CXX object _deps/minu...Files/Minuit2.dir/SimplexBuilder.cxx.o
[69/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/mnvert.cxx.o
[70/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mndasum.cxx.o
[70/80] Building CXX object _deps/minu.../CMakeFiles/Minuit2.dir/mnxerbla.cxx.o
[71/80] Building CXX object _deps/minu.../CMakeFiles/Minuit2.dir/mnteigen.cxx.o
[71/80] Linking CXX static library _deps/minuit2-build/src/math/libMinuit2Math.a
[72/80] Building CXX object _deps/minu...Minuit2.dir/SimplexSeedGenerator.cxx.o
[72/80] Building CXX object CMakeFiles/simpleminuit.dir/simpleminuit.cpp.o
[73/80] Building CXX object _deps/minu...c/CMakeFiles/Minuit2.dir/mntplot.cxx.o
[74/80] Building CXX object _deps/minu...rc/CMakeFiles/Minuit2.dir/mnvert.cxx.o
[75/80] Linking CXX static library _deps/minuit2-build/src/math/libMinuit2Math.a
[76/80] Building CXX object _deps/minu.../CMakeFiles/Minuit2.dir/mnxerbla.cxx.o
[77/80] Building CXX object _deps/minu...inuit2.dir/VariableMetricBuilder.cxx.o
[77/80] Linking CXX static library _deps/minuit2-build/src/libMinuit2.a
[78/80] Linking CXX static library _deps/minuit2-build/src/libMinuit2.a
[79/80] Building CXX object CMakeFiles/simpleminuit.dir/simpleminuit.cpp.o
[79/80] Linking CXX executable simpleminuit
[80/80] Linking CXX executable simpleminuit
!./build/simpleminuit
val = 1
val = 1.001
val = 0.999
val = 1.0006
val = 0.999402
val = -8.23008e-11
val = 0.000345267
val = -0.000345267
val = -8.23008e-11
val = 0.000345267
val = -0.000345267
val = 6.90533e-05
val = -6.90535e-05

  Valid         : yes
  Function calls: 13
  Minimum value : 6.773427082e-21
  Edm           : 6.773427082e-21
  Internal parameters: 
 -8.230083282e-11
  Internal covariance matrix: 
              1
  External parameters: 
  Pos |    Name    |  type   |      Value       |    Error +/-
    0 |          x |  free   | -8.230083282e-11 | 0.7071067812

Step 3: Bind parts we need#

  • subclassable FCNBase

  • MnUserParameters (constructor and Add(string, double, double))

  • MnMigrad (constructor and operator())

  • FunctionMinimum (cout)

%mkdir src

Overloads#

  • Pure virtual methods cannot be instantiated in C++

  • Have to provide “Trampoline class” to provide Python class

%%writefile src/FCNBase.cpp
#include "PyHeader.h"
class PyFCNBase : public FCNBase {
   public:
     using FCNBase::FCNBase;

     double operator()(const std::vector<double> &v) const override {
         PYBIND11_OVERLOAD_PURE_NAME(
             double, FCNBase, "__call__", operator(), v);}

     double Up() const override {
         PYBIND11_OVERLOAD_PURE(double, FCNBase, Up, );}
 };
void init_FCNBase(py::module &m) {
    py::class_<FCNBase, PyFCNBase>(m, "FCNBase")
         .def(py::init<>())
         .def("__call__", &FCNBase::operator())
         .def("Up", &FCNBase::Up);
}
Writing src/FCNBase.cpp

Overloaded function signatures:#

  • C++11 syntax: (bool (MnUserParameters::*)(const std::string &, double)) &MnUserParameters::Add

  • C++14 syntax: py::overload_cast<const std::string &, double>(&MnUserParameters::Add)

%%writefile src/MnUserParameters.cpp
#include "PyHeader.h"

void init_MnUserParameters(py::module &m) {
    py::class_<MnUserParameters>(m, "MnUserParameters")
        .def(py::init<>())
        .def("Add", (bool (MnUserParameters::*)(const std::string &, double)) &MnUserParameters::Add)
        .def("Add", (bool (MnUserParameters::*)(const std::string &, double, double)) &MnUserParameters::Add)
    ;
}
Writing src/MnUserParameters.cpp

Adding default arguments (and named arguments)#

  • Using ""_a literal, names and even defaults can be added

%%writefile src/MnMigrad.cpp
#include "PyHeader.h"
        
void init_MnMigrad(py::module &m) {
    py::class_<MnApplication>(m, "MnApplication")
        .def("__call__",
             &MnApplication::operator(),
             "Minimize the function, returns a function minimum",
             py::arg("maxfcn")    = 0,
             "tolerance"_a = 0.1);
    
    py::class_<MnMigrad, MnApplication>(m, "MnMigrad")
        .def(py::init<const FCNBase &, const MnUserParameters &, unsigned int>(),
             "fcn"_a, "par"_a, "stra"_a = 1)
    ;
}    
Writing src/MnMigrad.cpp

Lambda functions#

  • Pybind11 accepts lambda functions, as well

%%writefile src/FunctionMinimum.cpp
#include "PyHeader.h"

#include <sstream>
#include <Minuit2/MnPrint.h>

void init_FunctionMinimum(py::module &m) {
    py::class_<FunctionMinimum>(m, "FunctionMinimum")
        .def("__str__", [](const FunctionMinimum &self) {
            std::stringstream os;
            os << self;
            return os.str();
        })
    ;
}
Writing src/FunctionMinimum.cpp
%%writefile CMakeLists.txt

cmake_minimum_required(VERSION 3.18...3.25)
project(Minuit2SimpleExamle LANGUAGES CXX)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

include(FetchContent)
FetchContent_Declare(
  minuit2
  URL           https://github.com/root-project/root/archive/refs/tags/v6-26-10.tar.gz
  URL_HASH      SHA256=a84ed095252614c6e2084987fce9ce4a5a62057bfd5a4a2725123ca9f60f674f
  SOURCE_SUBDIR math/minuit2
  DOWNLOAD_NO_PROGRESS
  EXCLUDE_FROM_ALL
)
FetchContent_MakeAvailable(minuit2)

set(PYBIND11_FINDPYTHON ON)
find_package(pybind11)

file(GLOB OUTPUT src/*.cpp)
pybind11_add_module(minuit2 ${OUTPUT})
target_link_libraries(minuit2 PUBLIC Minuit2::Minuit2)

install(TARGETS minuit2 DESTINATION .)
Overwriting CMakeLists.txt

We can use this CMakeLists from scikit-build-core:

%%writefile pyproject.toml

[build-system]
requires = ["scikit-build-core>=0.8", "pybind11>=2.10"]
build-backend = "scikit_build_core.build"

[project]
name = "minuit2"
version = "6.26.10"
Writing pyproject.toml
!{sys.executable} -m pip wheel . -v
Processing /home/runner/work/se-for-sci/se-for-sci/content/week12/03-pybind
  Running command pip subprocess to install build dependencies
  Using pip 24.2 from /home/runner/work/se-for-sci/se-for-sci/.pixi/envs/default/lib/python3.12/site-packages/pip (python 3.12)
  Collecting scikit-build-core>=0.8
    Obtaining dependency information for scikit-build-core>=0.8 from https://files.pythonhosted.org/packages/20/f0/11b0f09173051647af2e140f68f3d94432c5b41a6ea0d45a43e38ab68192/scikit_build_core-0.10.5-py3-none-any.whl.metadata
    Downloading scikit_build_core-0.10.5-py3-none-any.whl.metadata (20 kB)
  Collecting pybind11>=2.10
    Obtaining dependency information for pybind11>=2.10 from https://files.pythonhosted.org/packages/04/e8/a22d08220cb5e230007d9b0c11e429c3b19d01315d1a99dbd45e3bf97386/pybind11-2.13.5-py3-none-any.whl.metadata
    Downloading pybind11-2.13.5-py3-none-any.whl.metadata (9.5 kB)
  Collecting packaging>=21.3 (from scikit-build-core>=0.8)
    Obtaining dependency information for packaging>=21.3 from https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl.metadata
    Downloading packaging-24.1-py3-none-any.whl.metadata (3.2 kB)
  Collecting pathspec>=0.10.1 (from scikit-build-core>=0.8)
    Obtaining dependency information for pathspec>=0.10.1 from https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl.metadata
    Downloading pathspec-0.12.1-py3-none-any.whl.metadata (21 kB)
  Downloading scikit_build_core-0.10.5-py3-none-any.whl (164 kB)
  Downloading pybind11-2.13.5-py3-none-any.whl (240 kB)
  Downloading packaging-24.1-py3-none-any.whl (53 kB)
  Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)
  Installing collected packages: pybind11, pathspec, packaging, scikit-build-core
    Creating /tmp/pip-build-env-np62jjlf/overlay/bin
    changing mode of /tmp/pip-build-env-np62jjlf/overlay/bin/pybind11-config to 755
  Successfully installed packaging-24.1 pathspec-0.12.1 pybind11-2.13.5 scikit-build-core-0.10.5
  Installing build dependencies ... ?25l?25hdone
  Running command Getting requirements to build wheel
  Getting requirements to build wheel ... ?25l?25hdone
  Running command Preparing metadata (pyproject.toml)
  *** scikit-build-core 0.10.5 using CMake 3.30.3 (metadata_wheel)
  2024-09-06 14:34:42,541 - scikit_build_core - WARNING - No license files found, set wheel.license-files to [] to suppress this warning
  Preparing metadata (pyproject.toml) ... ?25l?25hdone
Building wheels for collected packages: minuit2
  Running command Building wheel for minuit2 (pyproject.toml)
  *** scikit-build-core 0.10.5 using CMake 3.30.3 (wheel)
  2024-09-06 14:34:42,675 - scikit_build_core - WARNING - No license files found, set wheel.license-files to [] to suppress this warning
  *** Configuring CMake...
  loading initial cache file /tmp/tmpa82aeq62/build/CMakeInit.txt
  -- The CXX compiler identification is GNU 11.4.0
  -- Detecting CXX compiler ABI info
  -- Detecting CXX compiler ABI info - done
  -- Check for working CXX compiler: /usr/bin/g++ - skipped
  -- Detecting CXX compile features
  -- Detecting CXX compile features - done
  CMake Deprecation Warning at /tmp/tmpa82aeq62/build/_deps/minuit2-src/math/minuit2/CMakeLists.txt:7 (cmake_minimum_required):
    Compatibility with CMake < 3.5 will be removed from a future version of
    CMake.

    Update the VERSION argument <min> value or use a ...<max> suffix to tell
    CMake that the project does not need compatibility with older versions.

  
  CMake Deprecation Warning at /tmp/tmpa82aeq62/build/_deps/minuit2-src/math/minuit2/StandAlone.cmake:1 (cmake_minimum_required):
    Compatibility with CMake < 3.5 will be removed from a future version of
    CMake.

    Update the VERSION argument <min> value or use a ...<max> suffix to tell
    CMake that the project does not need compatibility with older versions.
  Call Stack (most recent call first):
    /tmp/tmpa82aeq62/build/_deps/minuit2-src/math/minuit2/CMakeLists.txt:250 (include)

  
  -- Found Python: /home/runner/work/se-for-sci/se-for-sci/.pixi/envs/default/bin/python (found suitable version "3.12.5", minimum required is "3.7") found components: Interpreter Development.Module Development.Embed
  -- Performing Test HAS_FLTO
  -- Performing Test HAS_FLTO - Success
  -- Found pybind11: /home/runner/work/se-for-sci/se-for-sci/.pixi/envs/default/lib/python3.12/site-packages/pybind11/include (found version "2.13.5")
  -- Configuring done (19.8s)
  -- Generating done (0.0s)
  -- Build files have been written to: /tmp/tmpa82aeq62/build
  *** Building project with Ninja...
  [1/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/DavidonErrorUpdator.cxx.o
  [2/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/AnalyticalGradientCalculator.cxx.o
  [3/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/BFGSErrorUpdator.cxx.o
  [4/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/CombinedMinimumBuilder.cxx.o
  [5/84] Building CXX object _deps/minuit2-build/src/math/CMakeFiles/Minuit2Math.dir/__/__/__/minuit2-src/math/mathcore/src/MinimizerOptions.cxx.o
  [6/84] Building CXX object _deps/minuit2-build/src/math/CMakeFiles/Minuit2Math.dir/__/__/__/minuit2-src/math/mathcore/src/GenAlgoOptions.cxx.o
  [7/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/ExternalInternalGradientCalculator.cxx.o
  [8/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/FumiliErrorUpdator.cxx.o
  [9/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/FumiliGradientCalculator.cxx.o
  [10/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/FumiliStandardChi2FCN.cxx.o
  [11/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/LaEigenValues.cxx.o
  [12/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/LaInnerProduct.cxx.o
  [13/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/FumiliMinimizer.cxx.o
  [14/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/FumiliStandardMaximumLikelihoodFCN.cxx.o
  [15/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/LaInverse.cxx.o
  [16/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/LaOuterProduct.cxx.o
  [17/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/LaSumOfElements.cxx.o
  [18/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/FumiliBuilder.cxx.o
  [19/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/HessianGradientCalculator.cxx.o
  [20/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/LaVtMVSimilarity.cxx.o
  [21/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/InitialGradientCalculator.cxx.o
  [22/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MPIProcess.cxx.o
  [23/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MinimumBuilder.cxx.o
  [24/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnEigen.cxx.o
  [25/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnFcn.cxx.o
  [26/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnCovarianceSqueeze.cxx.o
  [27/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnApplication.cxx.o
  [28/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnGlobalCorrelationCoeff.cxx.o
  [29/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnFumiliMinimize.cxx.o
  [30/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnMachinePrecision.cxx.o
  [31/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnContours.cxx.o
  [32/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnParabolaFactory.cxx.o
  [33/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnLineSearch.cxx.o
  [34/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnFunctionCross.cxx.o
  [35/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/Minuit2Minimizer.cxx.o
  [36/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnPlot.cxx.o
  [37/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnParameterScan.cxx.o
  [38/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnHesse.cxx.o
  [39/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnPrintImpl.cxx.o
  [40/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnMinos.cxx.o
  [41/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnStrategy.cxx.o
  [42/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnTiny.cxx.o
  [43/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnScan.cxx.o
  [44/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnPosDef.cxx.o
  [45/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnUserFcn.cxx.o
  [46/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnTraceObject.cxx.o
  [47/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnPrint.cxx.o
  [48/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnUserParameters.cxx.o
  [49/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnSeedGenerator.cxx.o
  [50/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnUserParameterState.cxx.o
  [51/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/ModularFunctionMinimizer.cxx.o
  [52/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/NegativeG2LineSearch.cxx.o
  [53/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/MnUserTransformation.cxx.o
  [54/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/ParametricFunction.cxx.o
  [55/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/SimplexParameters.cxx.o
  [56/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/SinParameterTransformation.cxx.o
  [57/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/SqrtLowParameterTransformation.cxx.o
  [58/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/Numerical2PGradientCalculator.cxx.o
  [59/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/SqrtUpParameterTransformation.cxx.o
  [60/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mnbins.cxx.o
  [61/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/VariableMetricEDMEstimator.cxx.o
  [62/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/ScanBuilder.cxx.o
  [63/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mndaxpy.cxx.o
  [64/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mnddot.cxx.o
  [65/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mndasum.cxx.o
  [66/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mndscal.cxx.o
  [67/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/SimplexSeedGenerator.cxx.o
  [68/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mnlsame.cxx.o
  [69/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mndspr.cxx.o
  [70/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mndspmv.cxx.o
  [71/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mntplot.cxx.o
  [72/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mnteigen.cxx.o
  [73/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mnvert.cxx.o
  [74/84] Linking CXX static library _deps/minuit2-build/src/math/libMinuit2Math.a
  [75/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/mnxerbla.cxx.o
  [76/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/SimplexBuilder.cxx.o
  [77/84] Building CXX object _deps/minuit2-build/src/CMakeFiles/Minuit2.dir/VariableMetricBuilder.cxx.o
  [78/84] Linking CXX static library _deps/minuit2-build/src/libMinuit2.a
  [79/84] Building CXX object CMakeFiles/minuit2.dir/src/pyminuit2.cpp.o
  [80/84] Building CXX object CMakeFiles/minuit2.dir/src/FunctionMinimum.cpp.o
  [81/84] Building CXX object CMakeFiles/minuit2.dir/src/MnUserParameters.cpp.o
  [82/84] Building CXX object CMakeFiles/minuit2.dir/src/MnMigrad.cpp.o
  [83/84] Building CXX object CMakeFiles/minuit2.dir/src/FCNBase.cpp.o
  [84/84] Linking CXX shared module minuit2.cpython-312-x86_64-linux-gnu.so
  lto-wrapper: warning: using serial compilation of 3 LTRANS jobs
  *** Installing project into wheel...
  -- Install configuration: "Release"
  -- Installing: /tmp/tmpa82aeq62/wheel/platlib/./minuit2.cpython-312-x86_64-linux-gnu.so
  *** Making wheel...
  *** Created minuit2-6.26.10-cp312-cp312-linux_x86_64.whl
  Building wheel for minuit2 (pyproject.toml) ... ?25l?25hdone
  Created wheel for minuit2: filename=minuit2-6.26.10-cp312-cp312-linux_x86_64.whl size=242106 sha256=06e1d807d48ec5b31e0abb55e5f0d7578dae413c93a8aa8fbfba7adbd3e5f815
  Stored in directory: /home/runner/.cache/pip/wheels/a7/55/a1/1e68c77b2029aa1d5ec12bc54d8e95881d40e02ef4a3e083a1
Successfully built minuit2

Usage#

We can now use our module! We’ll just grab the file we need out of the wheel instead of installing it:

import zipfile
from pathlib import Path

with zipfile.ZipFile(*Path.cwd().glob("minuit2-6.26.10-*.whl")) as f:
    for member in f.filelist:
        print(member.filename)
        if member.filename.startswith("minuit2."):
            f.extract(member, ".")
minuit2.cpython-312-x86_64-linux-gnu.so
minuit2-6.26.10.dist-info/METADATA
minuit2-6.26.10.dist-info/WHEEL
minuit2-6.26.10.dist-info/RECORD
import minuit2


class SimpleFCN(minuit2.FCNBase):
    def Up(self):
        return 0.5

    def __call__(self, v):
        print("val =", v[0])
        return v[0] ** 2
fcn = SimpleFCN()
upar = minuit2.MnUserParameters()
upar.Add("x", 1.0, 0.1)
migrad = minuit2.MnMigrad(fcn, upar)
minimum = migrad()
val = 1.0
val = 1.001
val = 0.999
val = 1.0005980198587356
val = 0.9994019801412644
val = -8.230083281546285e-11
val = 0.00034526688527999595
val = -0.0003452670498816616
val = -8.230083281546285e-11
val = 0.00034526688527999595
val = -0.0003452670498816616
val = 6.905331121533294e-05
val = -6.905347581699857e-05
print(minimum)
  Valid         : yes
  Function calls: 13
  Minimum value : 6.773427082e-21
  Edm           : 6.773427082e-21
  Internal parameters: 
 -8.230083282e-11
  Internal covariance matrix: 
              1
  External parameters: 
  Pos |    Name    |  type   |      Value       |    Error +/-
    0 |          x |  free   | -8.230083282e-11 | 0.7071067812

Done#