Package specific_analyses :: Package model_free :: Module optimisation
[hide private]
[frames] | no frames]

Source Code for Module specific_analyses.model_free.optimisation

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2002-2009,2011-2014 Edward d'Auvergne                         # 
  4  # Copyright (C) 2006 Chris MacRaild                                           # 
  5  # Copyright (C) 2007 Gary S Thompson                                          # 
  6  # Copyright (C) 2008 Sebastien Morin                                          # 
  7  #                                                                             # 
  8  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  9  #                                                                             # 
 10  # This program is free software: you can redistribute it and/or modify        # 
 11  # it under the terms of the GNU General Public License as published by        # 
 12  # the Free Software Foundation, either version 3 of the License, or           # 
 13  # (at your option) any later version.                                         # 
 14  #                                                                             # 
 15  # This program is distributed in the hope that it will be useful,             # 
 16  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 17  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 18  # GNU General Public License for more details.                                # 
 19  #                                                                             # 
 20  # You should have received a copy of the GNU General Public License           # 
 21  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 22  #                                                                             # 
 23  ############################################################################### 
 24   
 25  # Module docstring. 
 26  """The model-free analysis optimisation functions.""" 
 27   
 28  # Python module imports. 
 29  from minfx.generic import generic_minimise 
 30  from minfx.grid import grid, grid_point_array 
 31  from numpy import array, dot, float64 
 32  import sys 
 33   
 34  # relax module imports. 
 35  import lib.arg_check 
 36  from lib.errors import RelaxError, RelaxInfError, RelaxMultiVectorError, RelaxNaNError 
 37  from lib.float import isNaN, isInf 
 38  from lib.periodic_table import periodic_table 
 39  from lib.text.sectioning import subsection 
 40  from multi import Memo, Result_command, Slave_command 
 41  from pipe_control import pipes 
 42  from pipe_control.interatomic import return_interatom_list 
 43  from pipe_control.mol_res_spin import return_spin, return_spin_from_index 
 44  from specific_analyses.model_free.parameters import assemble_param_vector, disassemble_param_vector 
 45  from target_functions.mf import Mf 
 46   
 47   
48 -def disassemble_result(param_vector=None, func=None, iter=None, fc=None, gc=None, hc=None, warning=None, spin=None, sim_index=None, model_type=None, scaling_matrix=None):
49 """Disassemble the optimisation results. 50 51 @keyword param_vector: The model-free parameter vector. 52 @type param_vector: numpy array 53 @keyword func: The optimised chi-squared value. 54 @type func: float 55 @keyword iter: The number of optimisation steps required to find the minimum. 56 @type iter: int 57 @keyword fc: The function count. 58 @type fc: int 59 @keyword gc: The gradient count. 60 @type gc: int 61 @keyword hc: The Hessian count. 62 @type hc: int 63 @keyword warning: Any optimisation warnings. 64 @type warning: str or None 65 @keyword spin: The spin container. 66 @type spin: SpinContainer instance or None 67 @keyword sim_index: The Monte Carlo simulation index. 68 @type sim_index: int or None 69 @keyword model_type: The model-free model type, one of 'mf', 'local_tm', 'diff', or 70 'all'. 71 @type model_type: str 72 @keyword scaling_matrix: The diagonal, square scaling matrix. 73 @type scaling_matrix: numpy diagonal matrix 74 """ 75 76 # No result. 77 if param_vector is None: 78 return 79 80 # Alias the current data pipe. 81 cdp = pipes.get_pipe() 82 83 # Catch infinite chi-squared values. 84 if isInf(func): 85 raise RelaxInfError('chi-squared') 86 87 # Catch chi-squared values of NaN. 88 if isNaN(func): 89 raise RelaxNaNError('chi-squared') 90 91 # Scaling. 92 if scaling_matrix is not None: 93 param_vector = dot(scaling_matrix, param_vector) 94 95 # Check if the chi-squared value is lower. This allows for a parallelised grid search! 96 if sim_index == None: 97 # Get the correct value. 98 chi2 = None 99 if (model_type == 'mf' or model_type == 'local_tm') and hasattr(cdp, 'chi2'): 100 chi2 = spin.chi2 101 if (model_type == 'diff' or model_type == 'all') and hasattr(cdp, 'chi2'): 102 chi2 = cdp.chi2 103 104 # Spin text. 105 spin_text = '' 106 if spin != None and hasattr(spin, '_spin_ids') and len(spin._spin_ids): 107 spin_text = " for the spin '%s'" % spin._spin_ids[0] 108 109 # No improvement. 110 if chi2 != None and func >= chi2: 111 print("Discarding the optimisation results%s, the optimised chi-squared value is higher than the current value (%s >= %s)." % (spin_text, func, chi2)) 112 113 # Exit! 114 return 115 116 # New minimum. 117 else: 118 print("Storing the optimisation results%s, the optimised chi-squared value is lower than the current value (%s < %s)." % (spin_text, func, chi2)) 119 120 # Disassemble the parameter vector. 121 disassemble_param_vector(model_type, param_vector=param_vector, spin=spin, sim_index=sim_index) 122 123 # Monte Carlo minimisation statistics. 124 if sim_index != None: 125 # Sequence specific minimisation statistics. 126 if model_type == 'mf' or model_type == 'local_tm': 127 128 # Chi-squared statistic. 129 spin.chi2_sim[sim_index] = func 130 131 # Iterations. 132 spin.iter_sim[sim_index] = iter 133 134 # Function evaluations. 135 spin.f_count_sim[sim_index] = fc 136 137 # Gradient evaluations. 138 spin.g_count_sim[sim_index] = gc 139 140 # Hessian evaluations. 141 spin.h_count_sim[sim_index] = hc 142 143 # Warning. 144 spin.warning_sim[sim_index] = warning 145 146 # Global minimisation statistics. 147 elif model_type == 'diff' or model_type == 'all': 148 # Chi-squared statistic. 149 cdp.chi2_sim[sim_index] = func 150 151 # Iterations. 152 cdp.iter_sim[sim_index] = iter 153 154 # Function evaluations. 155 cdp.f_count_sim[sim_index] = fc 156 157 # Gradient evaluations. 158 cdp.g_count_sim[sim_index] = gc 159 160 # Hessian evaluations. 161 cdp.h_count_sim[sim_index] = hc 162 163 # Warning. 164 cdp.warning_sim[sim_index] = warning 165 166 # Normal statistics. 167 else: 168 # Sequence specific minimisation statistics. 169 if model_type == 'mf' or model_type == 'local_tm': 170 # Chi-squared statistic. 171 spin.chi2 = func 172 173 # Iterations. 174 spin.iter = iter 175 176 # Function evaluations. 177 spin.f_count = fc 178 179 # Gradient evaluations. 180 spin.g_count = gc 181 182 # Hessian evaluations. 183 spin.h_count = hc 184 185 # Warning. 186 spin.warning = warning 187 188 # Global minimisation statistics. 189 elif model_type == 'diff' or model_type == 'all': 190 # Chi-squared statistic. 191 cdp.chi2 = func 192 193 # Iterations. 194 cdp.iter = iter 195 196 # Function evaluations. 197 cdp.f_count = fc 198 199 # Gradient evaluations. 200 cdp.g_count = gc 201 202 # Hessian evaluations. 203 cdp.h_count = hc 204 205 # Warning. 206 cdp.warning = warning
207 208
209 -def minimise_data_setup(data_store, min_algor, num_data_sets, min_options, spin=None, sim_index=None):
210 """Set up all the data required for minimisation. 211 212 @param data_store: A data storage container. 213 @type data_store: class instance 214 @param min_algor: The minimisation algorithm to use. 215 @type min_algor: str 216 @param num_data_sets: The number of data sets. 217 @type num_data_sets: int 218 @param min_options: The minimisation options array. 219 @type min_options: list 220 @keyword spin: The spin data container. 221 @type spin: SpinContainer instance 222 @keyword sim_index: The optional MC simulation index. 223 @type sim_index: int 224 @return: An insane tuple. The full tuple is (ri_data, ri_data_err, equations, param_types, param_values, r, csa, num_frq, frq, num_ri, remap_table, noe_r1_table, ri_types, num_params, xh_unit_vectors, diff_type, diff_params) 225 @rtype: tuple 226 """ 227 228 # Initialise the data structures for the model-free function. 229 data_store.ri_data = [] 230 data_store.ri_data_err = [] 231 data_store.equations = [] 232 data_store.param_types = [] 233 data_store.param_values = None 234 data_store.r = [] 235 data_store.csa = [] 236 data_store.num_frq = [] 237 data_store.frq = [] 238 data_store.num_ri = [] 239 data_store.remap_table = [] 240 data_store.noe_r1_table = [] 241 data_store.ri_types = [] 242 data_store.gx = [] 243 data_store.gh = [] 244 data_store.num_params = [] 245 data_store.xh_unit_vectors = [] 246 if data_store.model_type == 'local_tm': 247 data_store.mf_params = [] 248 elif data_store.model_type == 'diff': 249 data_store.param_values = [] 250 251 # Set up the data for the back_calc function. 252 if min_algor == 'back_calc': 253 # The spin data. 254 data_store.ri_data = [0.0] 255 data_store.ri_data_err = [0.000001] 256 data_store.equations = [spin.equation] 257 data_store.param_types = [spin.params] 258 data_store.csa = [spin.csa] 259 data_store.num_frq = [1] 260 data_store.frq = [[min_options[3]]] 261 data_store.num_ri = [1] 262 data_store.remap_table = [[0]] 263 data_store.noe_r1_table = [[None]] 264 data_store.ri_types = [[min_options[2]]] 265 data_store.gx = [periodic_table.gyromagnetic_ratio(spin.isotope)] 266 267 # The interatomic data. 268 interatoms = return_interatom_list(spin_hash=spin._hash) 269 for i in range(len(interatoms)): 270 # No relaxation mechanism. 271 if not interatoms[i].dipole_pair: 272 continue 273 274 # The surrounding spins. 275 if data_store.spin_id != interatoms[i].spin_id1: 276 spin_id2 = interatoms[i].spin_id1 277 else: 278 spin_id2 = interatoms[i].spin_id2 279 spin2 = return_spin(spin_id=spin_id2) 280 281 # The data. 282 data_store.r = [interatoms[i].r] 283 data_store.gh = [periodic_table.gyromagnetic_ratio(spin2.isotope)] 284 if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere': 285 data_store.xh_unit_vectors = [interatoms[i].vector] 286 else: 287 data_store.xh_unit_vectors = [None] 288 289 # Count the number of model-free parameters for the spin index. 290 data_store.num_params = [len(spin.params)] 291 292 # Loop over the number of data sets. 293 for j in range(num_data_sets): 294 # Set the spin index and get the spin, if not already set. 295 if data_store.model_type == 'diff' or data_store.model_type == 'all': 296 spin_index = j 297 spin, data_store.spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True) 298 299 # Skip deselected spins. 300 if not spin.select: 301 continue 302 303 # Skip spins where there is no data or errors. 304 if not hasattr(spin, 'ri_data') or not hasattr(spin, 'ri_data_err'): 305 continue 306 307 # Make sure that the errors are strictly positive numbers. 308 for ri_id in cdp.ri_ids: 309 # Skip missing data. 310 if not ri_id in spin.ri_data_err: 311 continue 312 313 # Alias. 314 err = spin.ri_data_err[ri_id] 315 316 # Checks. 317 if err != None and err == 0.0: 318 raise RelaxError("Zero error for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (data_store.spin_id, ri_id)) 319 elif err != None and err < 0.0: 320 raise RelaxError("Negative error of %s for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (err, data_store.spin_id, ri_id)) 321 322 # The relaxation data optimisation structures. 323 data = relax_data_opt_structs(spin, sim_index=sim_index) 324 325 # Append the data. 326 data_store.ri_data.append(data[0]) 327 data_store.ri_data_err.append(data[1]) 328 data_store.num_frq.append(data[2]) 329 data_store.num_ri.append(data[3]) 330 data_store.ri_types.append(data[4]) 331 data_store.frq.append(data[5]) 332 data_store.remap_table.append(data[6]) 333 data_store.noe_r1_table.append(data[7]) 334 if sim_index == None or data_store.model_type == 'diff': 335 data_store.csa.append(spin.csa) 336 else: 337 data_store.csa.append(spin.csa_sim[sim_index]) 338 339 # Repackage the spin data. 340 data_store.equations.append(spin.equation) 341 data_store.param_types.append(spin.params) 342 data_store.gx.append(periodic_table.gyromagnetic_ratio(spin.isotope)) 343 344 # Repackage the interatomic data. 345 interatoms = return_interatom_list(spin_hash=spin._hash) 346 for i in range(len(interatoms)): 347 # No relaxation mechanism. 348 if not interatoms[i].dipole_pair: 349 continue 350 351 # The surrounding spins. 352 if data_store.spin_id != interatoms[i].spin_id1: 353 spin_id2 = interatoms[i].spin_id1 354 else: 355 spin_id2 = interatoms[i].spin_id2 356 spin2 = return_spin(spin_id=spin_id2) 357 358 # The data. 359 data_store.gh.append(periodic_table.gyromagnetic_ratio(spin2.isotope)) 360 if sim_index == None or data_store.model_type == 'diff' or not hasattr(interatoms[i], 'r_sim'): 361 data_store.r.append(interatoms[i].r) 362 else: 363 data_store.r.append(interatoms[i].r_sim[sim_index]) 364 365 # Vectors. 366 if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere': 367 # Check that this is a single vector! 368 if lib.arg_check.is_num_list(interatoms[i].vector[0], raise_error=False): 369 raise RelaxMultiVectorError(data_store.spin_id) 370 371 # Store the vector. 372 data_store.xh_unit_vectors.append(interatoms[i].vector) 373 374 # No vector. 375 else: 376 data_store.xh_unit_vectors.append(None) 377 378 # Stop - only one mechanism is current supported. 379 break 380 381 # Model-free parameter values. 382 if data_store.model_type == 'local_tm': 383 pass 384 385 # Count the number of model-free parameters for the spin index. 386 data_store.num_params.append(len(spin.params)) 387 388 # Repackage the parameter values for minimising just the diffusion tensor parameters. 389 if data_store.model_type == 'diff': 390 data_store.param_values.append(assemble_param_vector(model_type='mf')) 391 392 # Convert to numpy arrays. 393 for k in range(len(data_store.ri_data)): 394 data_store.ri_data[k] = array(data_store.ri_data[k], float64) 395 data_store.ri_data_err[k] = array(data_store.ri_data_err[k], float64) 396 397 # Diffusion tensor type. 398 if data_store.model_type == 'local_tm': 399 data_store.diff_type = 'sphere' 400 else: 401 data_store.diff_type = cdp.diff_tensor.type 402 403 # Package the diffusion tensor parameters. 404 data_store.diff_params = None 405 if data_store.model_type == 'mf': 406 # Spherical diffusion. 407 if data_store.diff_type == 'sphere': 408 data_store.diff_params = [cdp.diff_tensor.tm] 409 410 # Spheroidal diffusion. 411 elif data_store.diff_type == 'spheroid': 412 data_store.diff_params = [cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.theta, cdp.diff_tensor.phi] 413 414 # Ellipsoidal diffusion. 415 elif data_store.diff_type == 'ellipsoid': 416 data_store.diff_params = [cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.Dr, cdp.diff_tensor.alpha, cdp.diff_tensor.beta, cdp.diff_tensor.gamma] 417 elif min_algor == 'back_calc' and data_store.model_type == 'local_tm': 418 # Spherical diffusion. 419 data_store.diff_params = [spin.local_tm]
420 421
422 -def relax_data_opt_structs(spin, sim_index=None):
423 """Package the relaxation data into the data structures used for optimisation. 424 425 @param spin: The spin container to extract the data from. 426 @type spin: SpinContainer instance 427 @keyword sim_index: The optional MC simulation index. 428 @type sim_index: int 429 @return: The structures ri_data, ri_data_err, num_frq, num_ri, ri_ids, frq, remap_table, noe_r1_table. 430 @rtype: tuple 431 """ 432 433 # Initialise the data. 434 ri_data = [] 435 ri_data_err = [] 436 ri_labels = [] 437 frq = [] 438 remap_table = [] 439 noe_r1_table = [] 440 441 # Loop over the relaxation data. 442 for ri_id in cdp.ri_ids: 443 # Skip missing data. 444 if ri_id not in spin.ri_data: 445 continue 446 447 # The Rx data. 448 if sim_index == None: 449 data = spin.ri_data[ri_id] 450 else: 451 data = spin.ri_data_sim[ri_id][sim_index] 452 453 # The errors. 454 err = spin.ri_data_err[ri_id] 455 456 # Missing data, so don't add it. 457 if data == None or err == None: 458 continue 459 460 # Append the data and error. 461 ri_data.append(data) 462 ri_data_err.append(err) 463 464 # The labels. 465 ri_labels.append(cdp.ri_type[ri_id]) 466 467 # The frequencies. 468 if cdp.spectrometer_frq[ri_id] not in frq: 469 frq.append(cdp.spectrometer_frq[ri_id]) 470 471 # The remap table. 472 remap_table.append(frq.index(cdp.spectrometer_frq[ri_id])) 473 474 # The NOE to R1 mapping table. 475 noe_r1_table.append(None) 476 477 # The number of data sets. 478 num_ri = len(ri_data) 479 480 # Fill the NOE to R1 mapping table. 481 for i in range(num_ri): 482 # If the data corresponds to 'NOE', try to find if the corresponding R1 data. 483 if cdp.ri_type[cdp.ri_ids[i]] == 'NOE': 484 for j in range(num_ri): 485 if cdp.ri_type[cdp.ri_ids[j]] == 'R1' and cdp.spectrometer_frq[cdp.ri_ids[i]] == cdp.spectrometer_frq[cdp.ri_ids[j]]: 486 noe_r1_table[i] = j 487 488 # Return the structures. 489 return ri_data, ri_data_err, len(frq), num_ri, ri_labels, frq, remap_table, noe_r1_table
490 491 492
493 -class MF_memo(Memo):
494 """The model-free memo class. 495 496 Not quite a momento so a memo. 497 """ 498
499 - def __init__(self, model_free=None, model_type=None, spin=None, sim_index=None, scaling_matrix=None):
500 """Initialise the model-free memo class. 501 502 This memo stores the model-free class instance so that the disassemble_result() method can be called to store the optimisation results. The other args are those required by this method but not generated through optimisation. 503 504 @keyword model_free: The model-free class instance. 505 @type model_free: specific_analyses.model_free.Model_free instance 506 @keyword spin: The spin data container. If this argument is supplied, then the spin_id argument will be ignored. 507 @type spin: SpinContainer instance 508 @keyword sim_index: The optional MC simulation index. 509 @type sim_index: int 510 @keyword scaling_matrix: The diagonal, square scaling matrix. 511 @type scaling_matrix: numpy diagonal matrix 512 """ 513 514 # Execute the base class __init__() method. 515 super(MF_memo, self).__init__() 516 517 # Store the arguments. 518 self.model_free = model_free 519 self.model_type = model_type 520 self.spin = spin 521 self.sim_index = sim_index 522 self.scaling_matrix = scaling_matrix
523 524 525
526 -class MF_minimise_command(Slave_command):
527 """Command class for standard model-free minimisation.""" 528
529 - def __init__(self):
530 """Initialise the base class.""" 531 532 # Execute the base class __init__() method. 533 super(MF_minimise_command, self).__init__()
534 535
536 - def optimise(self):
537 """Model-free optimisation. 538 539 @return: The optimisation results consisting of the parameter vector, function value, iteration count, function count, gradient count, Hessian count, and warnings. 540 @rtype: tuple of numpy array, float, int, int, int, int, str 541 """ 542 543 # Minimisation. 544 results = generic_minimise(func=self.mf.func, dfunc=self.mf.dfunc, d2func=self.mf.d2func, args=(), x0=self.opt_params.param_vector, min_algor=self.opt_params.min_algor, min_options=self.opt_params.min_options, func_tol=self.opt_params.func_tol, grad_tol=self.opt_params.grad_tol, maxiter=self.opt_params.max_iterations, A=self.opt_params.A, b=self.opt_params.b, full_output=True, print_flag=self.opt_params.verbosity) 545 546 # Return the minfx results unmodified. 547 return results
548 549
550 - def run(self, processor, completed):
551 """Setup and perform the model-free optimisation.""" 552 553 # Initialise the function to minimise. 554 self.mf = Mf(init_params=self.opt_params.param_vector, model_type=self.data.model_type, diff_type=self.data.diff_type, diff_params=self.data.diff_params, scaling_matrix=self.data.scaling_matrix, num_spins=self.data.num_spins, equations=self.data.equations, param_types=self.data.param_types, param_values=self.data.param_values, relax_data=self.data.ri_data, errors=self.data.ri_data_err, bond_length=self.data.r, csa=self.data.csa, num_frq=self.data.num_frq, frq=self.data.frq, num_ri=self.data.num_ri, remap_table=self.data.remap_table, noe_r1_table=self.data.noe_r1_table, ri_labels=self.data.ri_types, gx=self.data.gx, gh=self.data.gh, h_bar=self.data.h_bar, mu0=self.data.mu0, num_params=self.data.num_params, vectors=self.data.xh_unit_vectors) 555 556 # Printout. 557 if self.opt_params.verbosity >= 1 and (self.data.model_type == 'mf' or self.data.model_type == 'local_tm'): 558 subsection(file=sys.stdout, text="Optimisation: Spin '%s'" % self.data.spin_id, prespace=2, postspace=0) 559 560 # Preform optimisation. 561 results = self.optimise() 562 563 # Disassemble the results list. 564 param_vector, func, iter, fc, gc, hc, warning = results 565 566 processor.return_object(MF_result_command(processor, self.memo_id, param_vector, func, iter, fc, gc, hc, warning, completed=False))
567 568
569 - def store_data(self, data, opt_params):
570 """Store all the data required for model-free optimisation. 571 572 @param data: The data used to initialise the model-free target function class. 573 @type data: class instance 574 @param opt_params: The parameters and data required for optimisation using minfx. 575 @type opt_params: class instance 576 """ 577 578 # Store the data. 579 self.data = data 580 self.opt_params = opt_params
581 582 583
584 -class MF_grid_command(MF_minimise_command):
585 """Command class for the model-free grid search.""" 586
587 - def __init__(self):
588 """Initialise all the data.""" 589 590 # Execute the base class __init__() method. 591 super(MF_grid_command, self).__init__()
592 593
594 - def optimise(self):
595 """Model-free grid search. 596 597 @return: The optimisation results consisting of the parameter vector, function value, iteration count, function count, gradient count, Hessian count, and warnings. 598 @rtype: tuple of numpy array, float, int, int, int, int, str 599 """ 600 601 # Normal grid search. 602 if not hasattr(self.opt_params, 'subdivision'): 603 results = grid(func=self.mf.func, args=(), num_incs=self.opt_params.inc, lower=self.opt_params.lower, upper=self.opt_params.upper, A=self.opt_params.A, b=self.opt_params.b, verbosity=self.opt_params.verbosity) 604 605 # Subdivided grid. 606 else: 607 results = grid_point_array(func=self.mf.func, args=(), points=self.opt_params.subdivision, verbosity=self.opt_params.verbosity) 608 609 # Unpack the results. 610 param_vector, func, iter, warning = results 611 fc = iter 612 gc = 0.0 613 hc = 0.0 614 615 # Return everything. 616 return param_vector, func, iter, fc, gc, hc, warning
617 618 619
620 -class MF_result_command(Result_command):
621 """Class for processing the model-free results.""" 622
623 - def __init__(self, processor, memo_id, param_vector, func, iter, fc, gc, hc, warning, completed):
624 """Set up the class, placing the minimisation results here.""" 625 626 # Execute the base class __init__() method. 627 super(MF_result_command, self).__init__(processor=processor, completed=completed) 628 629 # Store the arguments. 630 self.memo_id = memo_id 631 self.param_vector = param_vector 632 self.func = func 633 self.iter = iter 634 self.fc = fc 635 self.gc = gc 636 self.hc = hc 637 self.warning = warning
638 639
640 - def run(self, processor, memo):
641 """Disassemble the model-free optimisation results. 642 643 @param processor: Unused! 644 @type processor: None 645 @param memo: The model-free memo. 646 @type memo: memo 647 """ 648 649 # Disassemble the results. 650 disassemble_result(param_vector=self.param_vector, func=self.func, iter=self.iter, fc=self.fc, gc=self.gc, hc=self.hc, warning=self.warning, spin=memo.spin, sim_index=memo.sim_index, model_type=memo.model_type, scaling_matrix=memo.scaling_matrix)
651