Repository: fitbenchmarking/fitbenchmarking

Issue:
Multiple problem groups error
**Description of the error**
When you run multiple problem groups, for example `fitbenchmark examples/benchmark_problems/NIST/*` the minimizers in the options are written over and produces the following errors
```            
Minimizer: Newton-CG: scipy 2-point
Minimizer cannot be run with Controller with current "algorithm_type" option set.
Details: The minimizer selected, Newton-CG: scipy 2-point, is not within algorithm_check[options.algorithm_type] = ['Nelder-Mead', 'Powell', 'CG', 'BFGS', 'Newton-CG', 'L-BFGS-B', 'TNC', 'SLSQP']
```

**Describe the expected result**
Runs with multiple problem groups



Discussion:

Patch:
diff --git a/fitbenchmarking/cli/main.py b/fitbenchmarking/cli/main.py
index 1626ea33..818d199f 100755
--- a/fitbenchmarking/cli/main.py
+++ b/fitbenchmarking/cli/main.py
@@ -132,6 +132,9 @@ def run(problem_sets, options_file='', debug=False):
         result_dir.append(group_results_dir)
         groups.append(label)
 
+        # resets options to original values
+        options.reset()
+
     root = os.path.dirname(inspect.getfile(fitbenchmarking))
     template_dir = os.path.join(root, 'templates')
     env = Environment(loader=FileSystemLoader(template_dir))
diff --git a/fitbenchmarking/utils/options.py b/fitbenchmarking/utils/options.py
index 52ce7094..7cad4285 100644
--- a/fitbenchmarking/utils/options.py
+++ b/fitbenchmarking/utils/options.py
@@ -120,6 +120,9 @@ class Options(object):
         :param file_name: The options file to load
         :type file_name: str
         """
+        # stores the file name to be used to reset options for multiple
+        # problem groups
+        self.stored_file_name = file_name
         self.error_message = []
         self._results_dir = ''
         config = configparser.ConfigParser(converters={'list': read_list,
@@ -192,6 +195,12 @@ class Options(object):
         if self.error_message != []:
             raise OptionsError('\n'.join(self.error_message))
 
+    def reset(self):
+        """
+        Resets options object when running multiple problem groups.
+        """
+        self.__init__(self.stored_file_name)
+
     def read_value(self, func, option):
         """
         Helper function which loads in the value


Test patch:
diff --git a/fitbenchmarking/utils/tests/test_options_generic.py b/fitbenchmarking/utils/tests/test_options_generic.py
index 92db49cd..caca4bbb 100644
--- a/fitbenchmarking/utils/tests/test_options_generic.py
+++ b/fitbenchmarking/utils/tests/test_options_generic.py
@@ -1,6 +1,7 @@
 '''
 Test the options write function
 '''
+import copy
 import os
 import unittest
 
@@ -73,6 +74,13 @@ class OptionsWriteTests(unittest.TestCase):
 
         os.remove(new_file_name)
 
+        assert options.stored_file_name == self.options_file
+        assert new_options.stored_file_name == new_file_name
+
+        # Overwrite file names
+        options.stored_file_name = ""
+        new_options.stored_file_name = ""
+
         self.assertDictEqual(options.__dict__, new_options.__dict__)
 
     def test_user_section_valid(self):
@@ -106,6 +114,18 @@ class OptionsWriteTests(unittest.TestCase):
             Options(opts_file)
         os.remove(opts_file)
 
+    def test_options_reset(self):
+        """
+        Tests options reset
+        """
+        options = Options()
+        options_save = copy.copy(options)
+        options.minimizers = {}
+        options.software = ['updated_software1', 'updated_software2']
+
+        options.reset()
+        self.assertDictEqual(options.__dict__, options_save.__dict__)
+
 
 if __name__ == '__main__':
     unittest.main()