Skip to content

Commit

Permalink
Merge 95921de into ba4eb70
Browse files Browse the repository at this point in the history
  • Loading branch information
tyronerees committed Nov 1, 2019
2 parents ba4eb70 + 95921de commit fdbd4e4
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 9 deletions.
10 changes: 7 additions & 3 deletions docs/source/contributors/extending_fitbenchmarking.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ that the fitting software can use, and converting the result back to a
standardised format (numpy arrays). As well as this, the controller must be
written so that the fitting is separated from the preparation wherever possible
in order to give accurate timings for the fitting. Examples of these
controllers can be found in ``fitbenchmarking/fitting/software_controllers``.
controllers can be found in ``fitbenchmarking/fitting/controllers``.

In order to add a new controller, you will need to:

1. Create a new subclass of BaseSoftwareController in
``fitbenchmarking/fitting/software_controllers``.
``fitbenchmarking/fitting/controllers``.
This should implement 4 functions:

- ``__init__()``: Initialise anything that is needed specifically for the
Expand All @@ -93,12 +93,16 @@ In order to add a new controller, you will need to:
(``self.results``, ``self.final_params``, ``self.success``)

2. Import your controller and add it to the dictionary 'controllers' in
``fitbenchmarking/fitbenchmark_one_problem.py``
``fitbenchmarking/fitbenchmark_one_problem.py``.
For ease of maintainance, please add new controllers in alphabetical order.

3. Document the available minimizers (currently done by adding to
``fitbenchmarking/fitbenchmarking_default_options.json``)

4. Create tests for the software in
``fitbenchmarking/fitting/tests/test_controllers.py``.
Again, for ease of maintainance, please add new controllers in alphabetical order.
Unless the new controller is more complicated than the currently available
controllers, this can be done by following the example of the others.


10 changes: 9 additions & 1 deletion docs/source/users/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ These include:
The software to use in fitting as a string or list of strings.
Selected softwares will be benchmarked.

Available options are ``"mantid"``, ``"sasview"``, and ``"scipy"``.
Available options are ``"mantid"``, ``"sasview"``, ``"scipy"`` and ``"dfogn"``.

``results_dir``
---------------
Expand Down Expand Up @@ -118,11 +118,19 @@ Scipy:
- ``"dogbox"``
- ``"lm"``
- and ``"trf"``


Information about these can be found on the
`Scipy documentation
<https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.least_squares.html>`__

DFO-GN:
- ``"dfogn"``
Information about this can be found on the
`DFO-GN documentation
<http://people.maths.ox.ac.uk/robertsl/dfogn/>`__


``comparison_mode``
-------------------
The comparison mode is used when displaying results to select the value
Expand Down
7 changes: 6 additions & 1 deletion fitbenchmarking/fitbenchmark_one_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

from fitbenchmarking.fitting import misc
from fitbenchmarking.fitting.plotting import plot_helper, plots
try:
from fitbenchmarking.fitting.controllers.dfogn_controller import DFOGNController
except ImportError:
DFOGNController = None
try:
from fitbenchmarking.fitting.controllers.mantid_controller import MantidController
except ImportError:
Expand Down Expand Up @@ -41,7 +45,8 @@ def fitbm_one_prob(user_input, problem):

software = user_input.software.lower()

controllers = {'mantid': MantidController,
controllers = {'dfogn': DFOGNController,
'mantid': MantidController,
'sasview': SasviewController,
'scipy': ScipyController}

Expand Down
3 changes: 2 additions & 1 deletion fitbenchmarking/fitbenchmarking_default_options.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"Simplex","SteepestDescent",
"Trust Region"],
"scipy" : ["lm", "trf", "dogbox"],
"sasview" : ["amoeba", "lm", "newton", "de", "pt", "mp"]
"sasview" : ["amoeba", "lm", "newton", "de", "pt", "mp"],
"dfogn" : ["dfogn"]
},

"comparison_mode" : "both"
Expand Down
64 changes: 64 additions & 0 deletions fitbenchmarking/fitting/controllers/dfogn_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""
Implements a controller for DFO-GN
http://people.maths.ox.ac.uk/robertsl/dfogn/
"""

import dfogn
import numpy as np

from fitbenchmarking.fitting.controllers.base_controller import Controller

class DFOGNController(Controller):
"""
Controller for the DFO-GN fitting software.
"""

def __init__(self, problem, use_errors):
"""
Initialises variable used for temporary storage.
"""
super(DFOGNController, self).__init__(problem, use_errors)

self._soln = None
self._popt = None
self._pinit = None

def setup(self):
"""
Setup for DFO-GN
"""
self._pinit = np.asarray(self.initial_params)

def _prediction_error(self,p):
f = self.data_y - self.problem.eval_f(x=self.data_x,
params=p,
function_id=self.function_id)
if self.use_errors:
f = f/self.data_e

return f

def fit(self):
"""
Run problem with DFO-GN.
"""
self.success = False

self._soln = dfogn.solve(self._prediction_error,
self._pinit)

if (self._soln.flag == 0):
self.success = True

self._popt = self._soln.x

def cleanup(self):
"""
Convert the result to a numpy array and populate the variables results
will be read from.
"""
if self.success:
self.results = self.problem.eval_f(x=self.data_x,
params=self._popt,
function_id=self.function_id)
self.final_params = self._popt
14 changes: 12 additions & 2 deletions fitbenchmarking/fitting/tests/test_controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

from fitbenchmarking.fitting.controllers.base_controller import \
Controller
from fitbenchmarking.fitting.controllers.dfogn_controller import \
DFOGNController
from fitbenchmarking.fitting.controllers.mantid_controller import \
MantidController
from fitbenchmarking.fitting.controllers.sasview_controller import \
Expand All @@ -23,8 +25,8 @@ def misra1a_file():
main_dir = os.path.dirname(os.path.normpath(parent_dir))
root_dir = os.path.dirname(os.path.normpath(main_dir))
bench_prob_dir = os.path.join(root_dir, 'benchmark_problems')
fname = os.path.join(bench_prob_dir, 'NIST', 'low_difficulty',
'Misra1a.dat')
fname = os.path.join(bench_prob_dir, 'simple_tests',
'cubic.dat')

return fname

Expand Down Expand Up @@ -124,6 +126,14 @@ def test_scipy(self):
controller.minimizer = 'lm'
self.shared_testing(controller)

def test_dfogn(self):
"""
DFOGNController: Tests for output shape
"""
controller = DFOGNController(self.problem, True)
controller.minimizer = 'dfogn'
self.shared_testing(controller)

def shared_testing(self, controller):
"""
Utility function to run controller and check output is in generic form
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
license='GPL-3.0',
packages=find_packages(),
install_requires=['docutils', 'numpy<1.17', 'matplotlib<3.0',
'scipy>=0.18,<1.3', 'bumps', 'sasmodels', 'lxml'],
'scipy>=0.18,<1.3', 'bumps', 'sasmodels', 'lxml',
'dfogn'],
zip_safe=False,

cmdclass={
Expand Down

0 comments on commit fdbd4e4

Please sign in to comment.