## Minimizer settings

This example demonstrates how to change the minimizer algorithm and some of its settings. For example, the following lines

minimizer = ba.Minimizer()
minimizer.setMinimizer("Minuit2", "Migrad", "MaxFunctionCalls=500;Strategy=2")

will set the internal minimizer to “Minuit2”, its internal algorithm to “Migrad” and then pass additional options, limiting the maximum number of calls and an internal minimization strategy.

The list of available minimizers and their options can be seen with

print(ba.MinimizerFactory().catalogueDetailsToString())

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128  #!/usr/bin/env python3 """ Fitting example: running same fit using various minimizer and their settings. """ import bornagain as ba from bornagain import deg, angstrom, nm def get_sample(params): """ Returns a sample with uncorrelated cylinders and prisms on a substrate. """ cylinder_height = params["cylinder_height"] cylinder_radius = params["cylinder_radius"] prism_height = params["prism_height"] prism_base_edge = params["prism_base_edge"] # defining materials m_vacuum = ba.RefractiveMaterial("Vacuum", 0, 0) m_substrate = ba.RefractiveMaterial("Substrate", 6e-6, 2e-8) m_particle = ba.RefractiveMaterial("Particle", 6e-4, 2e-8) # collection of particles cylinder_ff = ba.Cylinder(cylinder_radius, cylinder_height) cylinder = ba.Particle(m_particle, cylinder_ff) prism_ff = ba.Prism3(prism_base_edge, prism_height) prism = ba.Particle(m_particle, prism_ff) layout = ba.ParticleLayout() layout.addParticle(cylinder, 0.5) layout.addParticle(prism, 0.5) interference = ba.InterferenceNone() layout.setInterference(interference) # vacuum layer with particles and substrate form multi layer vacuum_layer = ba.Layer(m_vacuum) vacuum_layer.addLayout(layout) substrate_layer = ba.Layer(m_substrate, 0) sample = ba.MultiLayer() sample.addLayer(vacuum_layer) sample.addLayer(substrate_layer) return sample def get_simulation(params): """ Returns a GISAXS simulation with beam and detector defined """ beam = ba.Beam(1e8, 1*angstrom, ba.Direction(0.2*deg, 0)) n = bp.simargs['n'] detector = ba.SphericalDetector(n, -1*deg, 1*deg, n, 0, 2*deg) return ba.ScatteringSimulation(beam, get_sample(params), detector) def create_real_data(): """ Generating "real" data from simulated image with default parameters. """ params = { 'cylinder_height': 5*nm, 'cylinder_radius': 5*nm, 'prism_height': 5*nm, 'prism_base_edge': 5*nm } simulation = get_simulation(params) result = simulation.simulate() return result.array() def run_fitting(): """ main function to run fitting """ real_data = create_real_data() # prints info about available minimizers print(ba.MinimizerFactory().catalogToString()) # prints detailed info about available minimizers and their options print(ba.MinimizerFactory().catalogDetailsToString()) fit_objective = ba.FitObjective() fit_objective.addSimulationAndData(get_simulation, real_data, 1) fit_objective.initPrint(10) params = ba.Parameters() params.add("cylinder_height", 4.*nm, min=0.01) params.add("cylinder_radius", 6.*nm, min=0.01) params.add("prism_height", 4.*nm, min=0.01) params.add("prism_base_edge", 12.*nm, min=0.01) minimizer = ba.Minimizer() # Uncomment one of the line below to adjust minimizer settings """ Setting Minuit2 minimizer with Migrad algorithm, limiting number of iterations. Minimization will try to respect MaxFunctionCalls value. """ # minimizer.setMinimizer("Minuit2", "Migrad", "MaxFunctionCalls=50") """ Setting two options at once. Strategy=2 promises more accurate fit. """ # minimizer.setMinimizer("Minuit2", "Migrad", "MaxFunctionCalls=500;Strategy=2") """ Setting Minuit2 minimizer with Fumili algorithm. """ # minimizer.setMinimizer("Minuit2", "Fumili") """ Setting Levenberg-Marquardt algorithm. """ # minimizer.setMinimizer("GSLLMA") result = minimizer.minimize(fit_objective.evaluate_residuals, params) fit_objective.finalize(result) print("Fitting completed.") print("chi2:", result.minValue()) for fitPar in result.parameters(): print(fitPar.name(), fitPar.value, fitPar.error) if __name__ == '__main__': run_fitting()