def solve(constraints, guess=None, nvars=None, solver=None, \ lower_bounds=None, upper_bounds=None, termination=None): """Use optimization to find a solution to a set of constraints. Inputs: constraints -- a constraints solver function or a penalty function Additional Inputs: guess -- list of parameter values proposed to solve the constraints. lower_bounds -- list of lower bounds on solution values. upper_bounds -- list of upper bounds on solution values. nvars -- number of parameter values. solver -- the mystic solver to use in the optimization termination -- the mystic termination to use in the optimization NOTE: The resulting constraints will likely be more expensive to evaluate and less accurate than writing the constraints solver from scratch. NOTE: The ensemble solvers are available, using the default NestedSolver, where the keyword 'guess' can be used to set the number of solvers. NOTE: The default solver is 'diffev', with npop=min(40, ndim*5). The default termination is ChangeOverGeneration(), and the default guess is randomly selected points between the upper and lower bounds. """ npts = 8 if type(guess) is int: npts, guess = guess, None ndim = 1 #XXX: better, increase in while loop catching IndexError ? if nvars is not None: ndim = nvars elif guess is not None: ndim = len(guess) elif lower_bounds is not None: ndim = len(lower_bounds) elif upper_bounds is not None: ndim = len(upper_bounds) def cost(x): return 1. #XXX: don't allow solver string as a short-cut? #FIXME: add ensemble solvers ensemble = False if solver is None or solver == 'diffev': from mystic.solvers import DifferentialEvolutionSolver as TheSolver solver = TheSolver(ndim, min(40, ndim * 5)) elif solver == 'diffev2': from mystic.solvers import DifferentialEvolutionSolver2 as TheSolver solver = TheSolver(ndim, min(40, ndim * 5)) elif solver == 'fmin_powell': #XXX: better as the default? (it's not random) from mystic.solvers import PowellDirectionalSolver as TheSolver solver = TheSolver(ndim) elif solver == 'fmin': from mystic.solvers import NelderMeadSimplexSolver as TheSolver solver = TheSolver(ndim) elif solver == 'buckshot': from mystic.solvers import BuckshotSolver as TheSolver solver = TheSolver(ndim, max(8, npts)) #XXX: needs better default? ensemble = True elif solver == 'lattice': from mystic.solvers import LatticeSolver as TheSolver solver = TheSolver(ndim, max(8, npts)) #XXX: needs better default? ensemble = True if termination is None: from mystic.termination import ChangeOverGeneration as COG termination = COG() if not ensemble: if guess is not None: solver.SetInitialPoints(guess) #XXX: nice if 'diffev' had methods else: solver.SetRandomInitialPoints(lower_bounds, upper_bounds) if lower_bounds or upper_bounds: solver.SetStrictRanges(lower_bounds, upper_bounds) if hasattr(constraints, 'iter') and hasattr(constraints, 'error'): solver.SetPenalty(constraints) #i.e. is a penalty function else: # is a constraints solver solver.SetConstraints(constraints) from numpy import seterr settings = seterr(all='ignore') solver.Solve(cost, termination) seterr(**settings) soln = solver.bestSolution from numpy import ndarray, array if isinstance(soln, ndarray) and not isinstance(guess, ndarray): soln = soln.tolist() elif isinstance(guess, ndarray) and not isinstance(soln, ndarray): soln = array(soln) #XXX: or always return a list ? return soln #XXX: check with 'issolution' ?
def solve(constraints, guess=None, nvars=None, solver=None, \ lower_bounds=None, upper_bounds=None, termination=None): """Use optimization to find a solution to a set of constraints. Inputs: constraints -- a constraints solver function or a penalty function Additional Inputs: guess -- list of parameter values proposed to solve the constraints. lower_bounds -- list of lower bounds on solution values. upper_bounds -- list of upper bounds on solution values. nvars -- number of parameter values. solver -- the mystic solver to use in the optimization termination -- the mystic termination to use in the optimization NOTE: The resulting constraints will likely be more expensive to evaluate and less accurate than writing the constraints solver from scratch. """ ndim = 1 #XXX: better, increase in while loop catching IndexError ? if nvars is not None: ndim = nvars elif guess is not None: ndim = len(guess) elif lower_bounds is not None: ndim = len(lower_bounds) elif upper_bounds is not None: ndim = len(upper_bounds) def cost(x): return 1. #XXX: don't allow solver string as a short-cut? if solver is None or solver == 'diffev': from mystic.solvers import DifferentialEvolutionSolver as TheSolver solver = TheSolver(ndim, min(40, ndim * 5)) elif solver == 'diffev2': from mystic.solvers import DifferentialEvolutionSolver2 as TheSolver solver = TheSolver(ndim, min(40, ndim * 5)) elif solver == 'fmin_powell': #XXX: better as the default? (it's not random) from mystic.solvers import PowellDirectionalSolver as TheSolver solver = TheSolver(ndim) elif solver == 'fmin': from mystic.solvers import NelderMeadSimplexSolver as TheSolver solver = TheSolver(ndim) if termination is None: from mystic.termination import ChangeOverGeneration as COG termination = COG() if guess != None: solver.SetInitialPoints(guess) #XXX: nice if 'diffev' also had methods else: solver.SetRandomInitialPoints(lower_bounds, upper_bounds) if lower_bounds or upper_bounds: solver.SetStrictRanges(lower_bounds, upper_bounds) if hasattr(constraints, 'iter') and hasattr(constraints, 'error'): solver.SetPenalty(constraints) #i.e. is a penalty function else: # is a constraints solver solver.SetConstraints(constraints) solver.Solve(cost, termination) soln = solver.bestSolution from numpy import ndarray, array if isinstance(soln, ndarray) and not isinstance(guess, ndarray): soln = soln.tolist() elif isinstance(guess, ndarray) and not isinstance(soln, ndarray): soln = array(soln) #XXX: or always return a list ? return soln #XXX: check with 'issolution' ?