ENV["PYTHON"]=""
using Pkg
Pkg.build("PyCall")
Pkg.add("BenchmarkTools")
using IMinuit
using BenchmarkTools
┌ Info: Precompiling IMinuit [beb75e20-2205-47e6-ad51-640e9c2309f1] └ @ Base loading.jl:1278
f(x) = x[1]^2 + (x[2]-1)^2 + (x[3]-2)^4
f1(x, y, z) = x^2 + (y-1)^2 + (z-2)^4
f1 (generic function with 1 method)
# using array parameters
m = Minuit(f, [1, 1, 4], fix_x0 = true)
migrad(m)
FCN = 1 | Ncalls = 45 (45 total) | |||
EDM = 2.47e-05 (Goal: 0.0002) | up = 1.0 | |||
Valid Minimum | Valid Parameters | No Parameters at limit | ||
Below EDM threshold (goal x 10) | Below call limit | |||
Hesse ok | Has Covariance | Accurate | Pos. def. | Not forced |
Name | Value | Hesse Error | Minos Error- | Minos Error+ | Limit- | Limit+ | Fixed | |
---|---|---|---|---|---|---|---|---|
0 | x0 | 1.00 | 0.01 | yes | ||||
1 | x1 | 1 | 1 | |||||
2 | x2 | 2 | 5 |
# a new fit can continue from the previous fit
m_new = Minuit(f, m, fix_x0 = false)
migrad(m_new)
FCN = 7.285e-06 | Ncalls = 40 (40 total) | |||
EDM = 4.85e-06 (Goal: 0.0002) | up = 1.0 | |||
Valid Minimum | Valid Parameters | No Parameters at limit | ||
Below EDM threshold (goal x 10) | Below call limit | |||
Hesse ok | Has Covariance | Accurate | Pos. def. | Not forced |
Name | Value | Hesse Error | Minos Error- | Minos Error+ | Limit- | Limit+ | Fixed | |
---|---|---|---|---|---|---|---|---|
0 | x0 | -0 | 1 | |||||
1 | x1 | 1 | 1 | |||||
2 | x2 | 2 | 8 |
# using array parameters, using `ForwardDiff: gradient` to compute the gradient
gradf(x) = gradient(f, x)
mgrad = Minuit(f, [1, 1, 4], grad = gradf)
migrad(mgrad)
FCN = 0.0001006 | Ncalls = 69 (69 total) | |||
EDM = 6.75e-05 (Goal: 0.0002) | up = 1.0 | |||
Valid Minimum | Valid Parameters | No Parameters at limit | ||
Below EDM threshold (goal x 10) | Below call limit | |||
Hesse ok | Has Covariance | Accurate | Pos. def. | Not forced |
Name | Value | Hesse Error | Minos Error- | Minos Error+ | Limit- | Limit+ | Fixed | |
---|---|---|---|---|---|---|---|---|
0 | x0 | 0 | 1 | |||||
1 | x1 | 1 | 1 | |||||
2 | x2 | 2 | 4 |
# parameters are given individually
m1 = Minuit(f1, x = 1, y = 1, z = 4)
migrad(m1)
FCN = 0.0001683 | Ncalls = 89 (89 total) | |||
EDM = 0.000115 (Goal: 0.0002) | up = 1.0 | |||
Valid Minimum | Valid Parameters | No Parameters at limit | ||
Below EDM threshold (goal x 10) | Below call limit | |||
Hesse ok | Has Covariance | Accurate | Pos. def. | Not forced |
Name | Value | Hesse Error | Minos Error- | Minos Error+ | Limit- | Limit+ | Fixed | |
---|---|---|---|---|---|---|---|---|
0 | x | 0 | 1 | |||||
1 | y | 1 | 1 | |||||
2 | z | 2 | 4 |
@show iminuit.__version__
propertynames(m)
iminuit.__version__ = "1.5.2"
104-element Array{Symbol,1}: :LEAST_SQUARES :LIKELIHOOD :__class__ :__delattr__ :__dir__ :__doc__ :__eq__ :__format__ :__ge__ :__getattribute__ :__gt__ :__hash__ :__init__ ⋮ :profile :set_errordef :set_print_level :set_strategy :set_up :strategy :throw_nan :tol :use_array_call :valid :values :var2pos
# the doc strings are from `iminuit`
@doc migrad
Docstring pulled from the Python `iminuit`: Minuit.migrad(self, ncall=None, resume=True, precision=None, iterate=5, **deprecated_kwargs) Run MIGRAD. MIGRAD is a robust minimisation algorithm which earned its reputation in 40+ years of almost exclusive usage in high-energy physics. How MIGRAD works is described in the `MINUIT paper`_. **Arguments:** * **ncall**: integer or None, optional; (approximate) maximum number of call before MIGRAD will stop trying. Default: None (indicates to use MIGRAD's internal heuristic). Note: MIGRAD may slightly violate this limit, because it checks the condition only after a full iteration of the algorithm, which usually performs several function calls. * **resume**: boolean indicating whether MIGRAD should resume from the previous minimiser attempt(True) or should start from the beginning(False). Default True. * **precision**: override Minuit precision estimate for the cost function. Default: None (= use epsilon of a C++ double). If the cost function has a lower precision (e.g. of a C++ float), setting this to a lower value will accelerate convergence and reduce the rate of unsuccessful convergence. * **iterate**: automatically call Migrad up to N times if convergence was not reached. Default: 5. This simple heuristic makes Migrad converge more often even if the numerical precision of the cost function is low. Setting this to 1 disables the feature. **Return:** :ref:`function-minimum-sruct`, list of :ref:`minuit-param-struct`
The data are taken from BES Collaboration, Phys. Rev. D 62 (2000) 032002.
Here we use a simple model, which is not meant to be the correct one, to fit to the data.
Pkg.add("CSV")
Pkg.add("DataFrames")
Pkg.add("Plots")
Pkg.add("LaTeXStrings")
Pkg.add("PyPlot")
UndefVarError: Pkg not defined Stacktrace: [1] top-level scope at In[13]:1 [2] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091 [3] execute_code(::String, ::String) at /home/guo/.julia/packages/IJulia/rWZ9e/src/execute_request.jl:27 [4] execute_request(::ZMQ.Socket, ::IJulia.Msg) at /home/guo/.julia/packages/IJulia/rWZ9e/src/execute_request.jl:86 [5] #invokelatest#1 at ./essentials.jl:710 [inlined] [6] invokelatest at ./essentials.jl:709 [inlined] [7] eventloop(::ZMQ.Socket) at /home/guo/.julia/packages/IJulia/rWZ9e/src/eventloop.jl:8 [8] (::IJulia.var"#15#18")() at ./task.jl:356
using CSV
using DataFrames
using Plots
pyplot(framestyle = :box, minorticks = 5)
using LaTeXStrings
┌ Info: Precompiling Plots [91a5bcdd-55d7-5caf-9e0b-520d859cae80] └ @ Base loading.jl:1278
data_df = DataFrame!(CSV.File("./testdata.csv"))
const data = Data(data_df)
Data([0.303, 0.309, 0.321, 0.327, 0.333, 0.339, 0.345, 0.351, 0.357, 0.363 … 0.531, 0.537, 0.543, 0.549, 0.555, 0.561, 0.567, 0.573, 0.579, 0.585], [8.522656, 44.87459, 29.63286, 58.13258, 28.2143, 129.0572, 181.7821, 199.5301, 269.4043, 186.1139 … 5217.45, 5867.647, 5717.979, 5527.38, 5548.063, 5386.82, 5425.564, 4744.075, 3899.626, 2725.864], [14.44523, 78.24785, 23.01279, 28.29703, 14.79316, 35.48893, 43.7948, 42.20547, 49.41916, 42.54225 … 164.0276, 174.4779, 169.0323, 165.0818, 164.632, 160.1847, 160.5301, 149.5817, 138.9569, 117.8775], 47)
@plt_data data xlab=L"m_{\pi\pi}"*" [GeV]" ylab="Events"
const M = 3.686; const mπ = 0.14; const mJ = 3.097;
λ(x, y, z) = x^2 + y^2 + z^2 - 2x*y - 2y*z - 2z*x
# a simple function that will be used to fit the data: QCD multipole expansion model for ψ'→J/ψπ⁺π⁻
# The important ππ FSI effect is not taken into account
# bg is just for introducing a third parameter
function dist(w, N, c, bg)
if (w ≤ 2mπ || w ≥ M-mJ)
res = 0.0
else
q1 = sqrt(λ(w^2, mπ^2, mπ^2))/(2w)
q2 = sqrt(λ(M^2, w^2, mJ^2))/(2M)
res = N * q1 * q2 * (w^2 - c*mπ^2)^2 + bg
end
return res * 1e6
end;
dist(x, p) = dist(x, p...)
dist (generic function with 2 methods)
# parameters given individually
χsq1(N, c, bg) = chisq(dist, data, (N, c, bg));
# all parameters are vairables of χsq
fit1 = Minuit(χsq1, N = 1, c = 2, bg = 0, error_N = 0.1, error_c = 0.1, error_bg = 0.1)
fit1.strategy = 1;
# parameters are collected into a tuple or an array, which is the only variable of χsq
parname = [:N, :c, :bg]
χsq(par) = chisq(dist, data, par)
gradf(par) = gradient(χsq, par)
fit = Minuit(χsq, [1, 2, 0], error = 0.1*ones(3), name = parname, grad = gradf)
fit.strategy = 1;
# or simply using model_fit or @model_fit
fit2 = model_fit(dist, data, [1, 2, 0], error = 0.1*ones(3), name = parname, fix_bg = true)
fit2.strategy = 1;
migrad(fit2)
FCN = 68.22 | Ncalls = 60 (60 total) | |||
EDM = 6.15e-05 (Goal: 0.0002) | up = 1.0 | |||
Valid Minimum | Valid Parameters | No Parameters at limit | ||
Below EDM threshold (goal x 10) | Below call limit | |||
Hesse ok | Has Covariance | Accurate | Pos. def. | Not forced |
Name | Value | Hesse Error | Minos Error- | Minos Error+ | Limit- | Limit+ | Fixed | |
---|---|---|---|---|---|---|---|---|
0 | N | 2.67 | 0.04 | |||||
1 | c | 4.33 | 0.06 | |||||
2 | bg | 0.0 | 0.1 | yes |
# the privous fit status can be passed to a new fit
fit2_new = model_fit(dist, data, fit2, name = parname, fix_bg = false)
migrad(fit2_new)
FCN = 64.68 | Ncalls = 65 (65 total) | |||
EDM = 2.08e-05 (Goal: 0.0002) | up = 1.0 | |||
Valid Minimum | Valid Parameters | No Parameters at limit | ||
Below EDM threshold (goal x 10) | Below call limit | |||
Hesse ok | Has Covariance | Accurate | Pos. def. | Not forced |
Name | Value | Hesse Error | Minos Error- | Minos Error+ | Limit- | Limit+ | Fixed | |
---|---|---|---|---|---|---|---|---|
0 | N | 2.61 | 0.05 | |||||
1 | c | 4.20 | 0.09 | |||||
2 | bg | -0.022e-3 | 0.012e-3 |
@btime migrad(fit)
minos(fit)
migrad(fit)
76.000 μs (1410 allocations: 35.81 KiB)
FCN = 64.68 | Ncalls = 3 (160323 total) | |||
EDM = 9.36e-15 (Goal: 0.0002) | up = 1.0 | |||
Valid Minimum | Valid Parameters | No Parameters at limit | ||
Below EDM threshold (goal x 10) | Below call limit | |||
Hesse ok | Has Covariance | Accurate | Pos. def. | Not forced |
Name | Value | Hesse Error | Minos Error- | Minos Error+ | Limit- | Limit+ | Fixed | |
---|---|---|---|---|---|---|---|---|
0 | N | 2.61 | 0.05 | -0.05 | 0.05 | |||
1 | c | 4.20 | 0.09 | -0.09 | 0.09 | |||
2 | bg | -0.022e-3 | 0.012e-3 | -0.012e-3 | 0.012e-3 |
@btime migrad(fit1)
minos(fit1)
migrad(fit1)
60.500 μs (479 allocations: 9.22 KiB)
FCN = 64.68 | Ncalls = 14 (951898 total) | |||
EDM = 1.52e-14 (Goal: 0.0002) | up = 1.0 | |||
Valid Minimum | Valid Parameters | No Parameters at limit | ||
Below EDM threshold (goal x 10) | Below call limit | |||
Hesse ok | Has Covariance | Accurate | Pos. def. | Not forced |
Name | Value | Hesse Error | Minos Error- | Minos Error+ | Limit- | Limit+ | Fixed | |
---|---|---|---|---|---|---|---|---|
0 | N | 2.61 | 0.05 | -0.05 | 0.05 | |||
1 | c | 4.20 | 0.09 | -0.09 | 0.09 | |||
2 | bg | -0.022e-3 | 0.012e-3 | -0.012e-3 | 0.012e-3 |
minos(fit1)
N | c | bg | ||||
---|---|---|---|---|---|---|
Error | -0.05 | 0.05 | -0.09 | 0.09 | -0.012e-3 | 0.012e-3 |
Valid | True | True | True | True | True | True |
At Limit | False | False | False | False | False | False |
Max FCN | False | False | False | False | False | False |
New Min | False | False | False | False | False | False |
# the ordering of dist, fit and data does not matter
@plt_best dist fit data
# MIGRAD contour of two parameters with the other ones fixed
# needs PyPlot or the pyplot backend of Plots
fit1.draw_contour(:N, :c, bound=3, bins=100)
([2.4561531846064364, 2.4592911671637516, 2.4624291497210673, 2.4655671322783825, 2.4687051148356978, 2.4718430973930134, 2.4749810799503287, 2.4781190625076444, 2.4812570450649596, 2.484395027622275 … 2.738571614764822, 2.7417095973221373, 2.7448475798794525, 2.747985562436768, 2.7511235449940834, 2.7542615275513986, 2.7573995101087143, 2.7605374926660295, 2.7636754752233452, 2.7668134577806605], [3.9216807759073293, 3.9273242217384023, 3.932967667569476, 3.938611113400549, 3.944254559231622, 3.9498980050626953, 3.9555414508937683, 3.9611848967248418, 3.9668283425559148, 3.972471788386988 … 4.429590900703915, 4.435234346534989, 4.440877792366061, 4.446521238197135, 4.452164684028208, 4.457808129859281, 4.463451575690354, 4.469095021521428, 4.4747384673525, 4.480381913183574], [20.972585684547113 20.022934908552898 … 290.280110975979 296.3574252092246; 21.148382447267153 20.131613966475754 … 285.0424527312081 291.0755140159173; … ; 350.8725474805894 342.54598215294766 … 19.826339420220364 20.935927070797632; 357.49518711030873 349.085022026704 … 19.595624194661738 20.647949873483995])
# contour of parameter space from MINOS
fit1.draw_mncontour(:N, :c, nsigma=3, numpoints=100)
Error in MnContours : unable to find point on Contour : i+1 = 6 Error in MnContours : found only i points : i = 5
PyObject <matplotlib.contour.ContourSet object at 0x7f1274744350>
matrix(fit1, correlation = true)
N | c | bg | |
---|---|---|---|
N | 1.00 | 0.93 | 0.61 |
c | 0.93 | 1.00 | 0.75 |
bg | 0.61 | 0.75 | 1.00 |
@show fit1.matrix
matrix(fit1)
fit1.matrix = ((0.0026808279257967637, 0.004460717050849894, 3.729529830296808e-7), (0.004460717050849894, 0.008670748910938015, 8.289868474538332e-7), (3.729529830296808e-7, 8.289868474538332e-7, 1.4150579833676482e-10))
N | c | bg | |
---|---|---|---|
N | 0.003 | 0.004 | 0.000 |
c | 0.004 | 0.009 | 0.000 |
bg | 0.000 | 0.000 | 0.000 |
# this gives parameter sets at the 1σ boundary
@time contour_df(fit1, χsq1, npts = 5)
0.030399 seconds (56.06 k allocations: 1.447 MiB)
chisq | N | c | bg | |
---|---|---|---|---|
Float64 | Float64 | Float64 | Float64 | |
1 | 64.6799 | 2.61148 | 4.20103 | -2.19212e-5 |
2 | 65.6799 | 2.56003 | 4.11414 | -2.93031e-5 |
3 | 65.6799 | 2.66359 | 4.28643 | -1.48855e-5 |
4 | 65.68 | 2.56385 | 4.10711 | -3.10184e-5 |
5 | 65.6799 | 2.65961 | 4.29336 | -1.32339e-5 |
6 | 65.68 | 2.5798 | 4.13027 | -3.39527e-5 |
7 | 65.68 | 2.64221 | 4.2688 | -1.01556e-5 |
8 | 65.68 | 2.56003 | 4.11439 | -2.92436e-5 |
9 | 65.6799 | 2.5638 | 4.10711 | -3.10202e-5 |
10 | 65.68 | 2.62543 | 4.19027 | -2.56233e-5 |
11 | 65.6799 | 2.66359 | 4.28649 | -1.48948e-5 |
12 | 65.6799 | 2.65962 | 4.29336 | -1.32556e-5 |
13 | 65.68 | 2.56003 | 4.11426 | -2.92484e-5 |
14 | 65.6801 | 2.57964 | 4.13014 | -3.39527e-5 |
15 | 65.6799 | 2.62161 | 4.19628 | -2.97972e-5 |
16 | 65.68 | 2.66359 | 4.28615 | -1.48963e-5 |
17 | 65.68 | 2.64229 | 4.26894 | -1.01556e-5 |
18 | 65.68 | 2.56393 | 4.10711 | -3.10364e-5 |
19 | 65.68 | 2.5797 | 4.12981 | -3.39527e-5 |
20 | 65.68 | 2.62357 | 4.21158 | -2.87507e-5 |
21 | 65.68 | 2.65952 | 4.29336 | -1.32348e-5 |
22 | 65.6799 | 2.64226 | 4.26916 | -1.01556e-5 |
# random sampling of parameters in given ranges, keeping those within 1σ
@time parsam_df = contour_df_samples(fit1, χsq1, (:N, :c), ([2.5,2.8], [4.0,4.3]), nsamples = 3000)
1.121674 seconds (2.72 M allocations: 87.125 MiB, 4.58% gc time)
chisq | N | c | bg | |
---|---|---|---|---|
Float64 | Float64 | Float64 | Float64 | |
1 | 64.6799 | 2.61148 | 4.20103 | -2.19212e-5 |
2 | 65.5073 | 2.56962 | 4.11594 | -3.03416e-5 |
3 | 64.9254 | 2.63565 | 4.23498 | -1.96192e-5 |
4 | 65.6177 | 2.56222 | 4.12314 | -2.8078e-5 |
5 | 64.8431 | 2.62984 | 4.23828 | -1.82591e-5 |
6 | 65.6722 | 2.66245 | 4.27809 | -1.61106e-5 |
7 | 65.1872 | 2.62854 | 4.20707 | -2.32734e-5 |
8 | 65.1948 | 2.64385 | 4.26689 | -1.54546e-5 |
9 | 64.9147 | 2.58663 | 4.15745 | -2.57081e-5 |
10 | 64.9352 | 2.63525 | 4.23278 | -1.99227e-5 |
11 | 64.9659 | 2.63194 | 4.24758 | -1.70113e-5 |
12 | 65.1888 | 2.63605 | 4.22287 | -2.16651e-5 |
13 | 65.5824 | 2.63104 | 4.20277 | -2.43333e-5 |
14 | 65.2395 | 2.60143 | 4.20987 | -1.90993e-5 |
15 | 64.7876 | 2.60674 | 4.20427 | -2.07278e-5 |
16 | 64.7876 | 2.62744 | 4.23148 | -1.90953e-5 |
17 | 64.9752 | 2.59003 | 4.17756 | -2.28542e-5 |
18 | 65.4389 | 2.57312 | 4.15265 | -2.46366e-5 |
19 | 65.6606 | 2.64755 | 4.2852 | -1.29847e-5 |
20 | 64.7571 | 2.59713 | 4.17676 | -2.39796e-5 |
21 | 65.1569 | 2.59943 | 4.20397 | -1.97807e-5 |
22 | 64.6919 | 2.61264 | 4.19917 | -2.23931e-5 |
23 | 65.1956 | 2.61824 | 4.18736 | -2.51283e-5 |
24 | 65.5094 | 2.57392 | 4.15735 | -2.3969e-5 |
25 | 64.9619 | 2.61424 | 4.22427 | -1.85054e-5 |
26 | 65.0639 | 2.59223 | 4.15125 | -2.75959e-5 |
27 | 65.1067 | 2.59923 | 4.20217 | -2.00465e-5 |
28 | 64.7869 | 2.61364 | 4.21607 | -1.97349e-5 |
29 | 65.3967 | 2.60654 | 4.16305 | -2.76185e-5 |
30 | 65.5409 | 2.65855 | 4.27099 | -1.67528e-5 |
⋮ | ⋮ | ⋮ | ⋮ | ⋮ |
# get parameter ranges
extrema(parsam_df.:N), extrema(parsam_df.:c)
((2.5616205401800602, 2.662654218072691), (4.111337112370791, 4.290896965655218))
scatter(parsam_df.:N, parsam_df.:c, xlab = "N", ylab = "c")
@time contour_df_samples(fit, χsq, (:x0, :x1, :x2), ([2.5,2.8], [4.0,4.3], (-3e-5,3e-5)), nsamples = 1000)
0.256838 seconds (619.84 k allocations: 22.200 MiB)
chisq | x0 | x1 | x2 | |
---|---|---|---|---|
Float64 | Float64 | Float64 | Float64 | |
1 | 64.6799 | 2.61148 | 4.20103 | -2.19212e-5 |
2 | 65.1487 | 2.58529 | 4.15465 | -2.26727e-5 |
3 | 65.3413 | 2.59429 | 4.18168 | -1.76276e-5 |
4 | 64.9135 | 2.61471 | 4.19279 | -2.58559e-5 |
5 | 65.4099 | 2.62823 | 4.23003 | -2.52553e-5 |
6 | 64.8081 | 2.61441 | 4.21532 | -1.82282e-5 |
7 | 64.9823 | 2.61652 | 4.1961 | -2.05706e-5 |
8 | 64.9631 | 2.58769 | 4.16366 | -2.67568e-5 |
9 | 65.6156 | 2.58318 | 4.17237 | -2.71772e-5 |
10 | 65.4836 | 2.65015 | 4.25285 | -2.13514e-5 |
11 | 65.6701 | 2.56547 | 4.10961 | -2.93393e-5 |
12 | 65.2734 | 2.63213 | 4.21562 | -2.4955e-5 |
13 | 65.1976 | 2.62462 | 4.24655 | -1.62462e-5 |
14 | 65.4716 | 2.62973 | 4.24865 | -2.13514e-5 |
@time contour_df_samples(fit, χsq, :x0, (2.5,2.8), nsamples = 20)
0.056369 seconds (340.98 k allocations: 7.254 MiB)
chisq | x0 | x1 | x2 | |
---|---|---|---|---|
Float64 | Float64 | Float64 | Float64 | |
1 | 64.6799 | 2.61148 | 4.20103 | -2.19212e-5 |
2 | 65.5614 | 2.56316 | 4.11968 | -2.88302e-5 |
3 | 65.0779 | 2.57895 | 4.14646 | -2.65198e-5 |
4 | 64.785 | 2.59474 | 4.17304 | -2.42721e-5 |
5 | 64.6803 | 2.61053 | 4.19944 | -2.20544e-5 |
6 | 64.7617 | 2.62632 | 4.2256 | -1.98768e-5 |
7 | 65.0271 | 2.64211 | 4.2515 | -1.77407e-5 |
8 | 65.4744 | 2.65789 | 4.27721 | -1.56345e-5 |
The example is Example A: Fit of a gaussian model to a histogram
Pkg.add("SpecialFunctions")
using PyCall
# import numpy from Python to generate the same data as in the example
np = pyimport(:numpy)
default_rng = pyimport("numpy.random").default_rng
rng = default_rng(seed=1)
const w, xe = np.histogram(rng.normal(0, 1, 10000), bins=1000)
([1, 0, 0, 0, 0, 0, 0, 0, 0, 0 … 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [-3.8378621427178974, -3.830092502694802, -3.8223228626717063, -3.8145532226486107, -3.806783582625515, -3.7990139426024196, -3.791244302579324, -3.7834746625562286, -3.775705022533133, -3.7679353825100375 … 3.8618511201697956, 3.869620760192891, 3.8773904002159867, 3.8851600402390822, 3.892929680262178, 3.9006993202852733, 3.908468960308369, 3.9162386003314644, 3.92400824035456, 3.931777880377655])
# define the model and the score function to minimize
using SpecialFunctions
function cdf(x, par)
mu, sigma = par
z = (x - mu) / sigma
return 0.5 * (1 + erf(z / sqrt(2)))
end
function score(par)
amp = par[1]
rest = par[2:end]
mu = amp * (cdf.(xe[2:end], Ref(rest)) - cdf.(xe[1:end-1], Ref(rest)) )
return 2 * sum(@. mu - w * log(mu + 1e-100))
end
score (generic function with 1 method)
const start_values = [1.5 * sum(w), 1.0, 2.0]
const limits = [(0, nothing), nothing, (0, nothing)];
# w/o grad
m = Minuit(score, start_values, limit=limits)
m.strategy = 0
# using grad
grad_fd(pars) = gradient(score, pars)
m_fd = Minuit(score, start_values, limit=limits, grad = grad_fd)
m_fd.strategy = 0;
@btime migrad(m)
627.100 μs (475 allocations: 460.64 KiB)
FCN = -3.871e+04 | Ncalls = 8 (39692 total) | |||
EDM = 2.01e-12 (Goal: 0.0002) | up = 1.0 | |||
Valid Min. | Valid Param. | Above EDM | Reached call limit | |
True | True | False | False | |
Hesse failed | Has cov. | Accurate | Pos. def. | Forced |
False | True | True | True | False |
Name | Value | Hesse Error | Minos Error- | Minos Error+ | Limit- | Limit+ | Fixed | |
---|---|---|---|---|---|---|---|---|
0 | x0 | 10.0e3 | 0.1e3 | 0 | ||||
1 | x1 | -0.011 | 0.010 | |||||
2 | x2 | 0.999 | 0.007 | 0 |
@btime migrad(m_fd)
380.300 μs (257 allocations: 348.22 KiB)
FCN = -3.871e+04 | Ncalls = 3 (27164 total) | |||
EDM = 9.41e-12 (Goal: 0.0002) | up = 1.0 | |||
Valid Min. | Valid Param. | Above EDM | Reached call limit | |
True | True | False | False | |
Hesse failed | Has cov. | Accurate | Pos. def. | Forced |
False | True | True | True | False |
Name | Value | Hesse Error | Minos Error- | Minos Error+ | Limit- | Limit+ | Fixed | |
---|---|---|---|---|---|---|---|---|
0 | x0 | 10.0e3 | 0.1e3 | 0 | ||||
1 | x1 | -0.011 | 0.010 | |||||
2 | x2 | 0.999 | 0.007 | 0 |