def optimize(cost, bounds, tolerance, _constraints): (lb, ub) = bounds from mystic.solvers import DifferentialEvolutionSolver2 from mystic.termination import VTR from mystic.strategy import Best1Exp from mystic.monitors import VerboseMonitor, Monitor from mystic.tools import random_seed if debug: random_seed(123) evalmon = Monitor() stepmon = Monitor() if debug: stepmon = VerboseMonitor(10) ndim = len(lb) solver = DifferentialEvolutionSolver2(ndim, npop) solver.SetRandomInitialPoints(min=lb, max=ub) solver.SetStrictRanges(min=lb, max=ub) solver.SetEvaluationLimits(maxiter, maxfun) solver.SetEvaluationMonitor(evalmon) solver.SetGenerationMonitor(stepmon) solver.Solve(cost,termination=VTR(tolerance),strategy=Best1Exp, \ CrossProbability=crossover,ScalingFactor=percent_change, \ constraints = _constraints) solved = solver.Solution() diameter_squared = solver.bestEnergy func_evals = len(evalmon) return solved, diameter_squared, func_evals
def main(): solver = DifferentialEvolutionSolver(ND, NP) solver.SetRandomInitialPoints() solver.SetEvaluationLimits(generations=MAX_GENERATIONS) solver.SetGenerationMonitor(VerboseMonitor(10)) #strategy = Best1Exp #strategy = Best1Bin #strategy = Best2Bin strategy = Best2Exp solver.Solve(ChebyshevCost, termination=VTR(0.0001), strategy=strategy, \ CrossProbability=1.0, ScalingFactor=0.6) solution = solver.Solution() print("\nsolved: ") print(poly1d(solution)) print("\ntarget: ") print(poly1d(Chebyshev16)) #print("actual coefficients vs computed:") #for actual,computed in zip(Chebyshev16, solution): # print("%f %f" % (actual, computed)) plot_solution(solution, Chebyshev16)
def optimize(cost,_bounds,_constraints): from mystic.solvers import DifferentialEvolutionSolver2 from mystic.termination import ChangeOverGeneration as COG from mystic.strategy import Best1Exp from mystic.monitors import VerboseMonitor, Monitor from mystic.tools import random_seed from mystic.termination import Or, CollapseWeight, CollapsePosition, state if debug: random_seed(123) # or 666 to force impose_unweighted reweighting stepmon = VerboseMonitor(1,1) else: stepmon = VerboseMonitor(10) if verbose else Monitor() stepmon._npts = npts evalmon = Monitor() lb,ub = _bounds ndim = len(lb) solver = DifferentialEvolutionSolver2(ndim,npop) solver.SetRandomInitialPoints(min=lb,max=ub) solver.SetStrictRanges(min=lb,max=ub) solver.SetEvaluationLimits(maxiter,maxfun) solver.SetEvaluationMonitor(evalmon) solver.SetGenerationMonitor(stepmon) solver.SetConstraints(_constraints) tol = convergence_tol term = Or(COG(tol,ngen), CollapseWeight(), CollapsePosition()) solver.Solve(cost,termination=term,strategy=Best1Exp, disp=verbose, \ CrossProbability=crossover,ScalingFactor=percent_change) #while collapse and solver.Collapse(verbose): #XXX: total_evaluations? # if debug: print(state(solver._termination).keys()) # solver.Solve() #XXX: cost, term, strategy, cross, scale ? # if debug: solver.SaveSolver('debug.pkl') solved = solver.bestSolution #print("solved: %s" % solver.Solution()) func_max = MINMAX * solver.bestEnergy #NOTE: -solution assumes -Max #func_max = 1.0 + MINMAX*solver.bestEnergy #NOTE: 1-sol => 1-success = fail func_evals = solver.evaluations from mystic.munge import write_support_file write_support_file(stepmon, npts=npts) return solved, func_max, func_evals
def fmin_powell(cost, x0, full=1, disp=1, monitor=0): """ change default behavior for selected optimizers """ from mystic.solvers import fmin_powell as solver from mystic.monitors import Monitor, VerboseMonitor if monitor: mon = VerboseMonitor(10) else: mon = Monitor() npop = 10*len(x0) solved = solver(cost, x0, npop=npop, full_output=full, disp=disp, itermon=mon, handler=0) # return: solution, energy, generations, fevals return solved[0], solved[1], solved[3], solved[4]
def mystic_optimize(point): from mystic.monitors import Monitor, VerboseMonitor from mystic.tools import getch, random_seed random_seed(123) from mystic.solvers import NelderMeadSimplexSolver as fmin from mystic.termination import CandidateRelativeTolerance as CRT simplex, esow = VerboseMonitor(50), Monitor() solver = fmin(len(point)) solver.SetInitialPoints(point) solver.SetEvaluationMonitor(esow) solver.SetGenerationMonitor(simplex) solver.Solve(cost_function, CRT()) solution = solver.Solution() return solution
def mystic_optimize(point): from mystic.monitors import Monitor, VerboseMonitor from mystic.solvers import NelderMeadSimplexSolver as fmin from mystic.termination import CandidateRelativeTolerance as CRT simplex, esow = VerboseMonitor(50), Monitor() solver = fmin(len(point)) solver.SetInitialPoints(point) min = [-100,-100,-100]; max = [100,100,100] solver.SetStrictRanges(min,max) solver.SetEvaluationMonitor(esow) solver.SetGenerationMonitor(simplex) solver.Solve(cost_function, CRT(1e-7,1e-7)) solution = solver.Solution() return solution
def mystic_optimize2(point): from mystic.monitors import Monitor, VerboseMonitor from mystic.tools import getch, random_seed random_seed(123) from mystic.solvers import DifferentialEvolutionSolver as de from mystic.termination import ChangeOverGeneration as COG NPOP = 50 simplex, esow = VerboseMonitor(50), Monitor() solver = de(len(point),NPOP) solver.SetInitialPoints(point) solver.SetEvaluationMonitor(esow) solver.SetGenerationMonitor(simplex) solver.Solve(cost_function, COG(generations=100), \ CrossProbability=0.5, ScalingFactor=0.5) solution = solver.Solution() return solution
def main(): solver = DifferentialEvolutionSolver(ND, NP) solver.SetRandomInitialPoints(min=[-100.0] * ND, max=[100.0] * ND) solver.SetEvaluationLimits(generations=MAX_GENERATIONS) solver.SetGenerationMonitor(VerboseMonitor(30)) solver.enable_signal_handler() strategy = Best1Exp #strategy = Best1Bin solver.Solve(ChebyshevCost, termination=VTR(0.01), strategy=strategy, \ CrossProbability=1.0, ScalingFactor=0.9, \ sigint_callback=plot_solution) solution = solver.Solution() return solution
def optimizeDE(cost, xmin, xmax, npop=40, maxiter=1000, maxfun=1e+6, convergence_tol=1e-5, ngen=100, crossover=0.9, percent_change=0.9, MINMAX=1, x0=[], radius=0.2, parallel=False, nodes=16): from mystic.solvers import DifferentialEvolutionSolver2 from mystic.termination import ChangeOverGeneration as COG from mystic.strategy import Best1Exp from mystic.monitors import VerboseMonitor, Monitor from pathos.helpers import freeze_support freeze_support() # help Windows use multiprocessing stepmon = VerboseMonitor(20) # step for showing live update evalmon = Monitor() ndim = len(xmin) solver = DifferentialEvolutionSolver2(ndim, npop) if parallel: solver.SetMapper(Pool(nodes).map) if x0 == []: solver.SetRandomInitialPoints(xmin, xmax) else: solver.SetInitialPoints(x0, radius) solver.SetStrictRanges(xmin, xmax) solver.SetEvaluationLimits(maxiter, maxfun) solver.SetEvaluationMonitor(evalmon) solver.SetGenerationMonitor(stepmon) tol = convergence_tol solver.Solve(cost, termination=COG(tolerance=tol, generations=ngen), strategy=Best1Exp, CrossProbability=crossover, ScalingFactor=percent_change) solved = solver.bestSolution func_max = MINMAX * solver.bestEnergy func_evals = solver.evaluations return solved, func_max, func_evals
def main(): solver = DifferentialEvolutionSolver(ND, NP) solver.SetRandomInitialPoints(min=[-100.0] * ND, max=[100.0] * ND) solver.SetEvaluationLimits(generations=MAX_GENERATIONS) solver.enable_signal_handler() strategy = Best1Bin stepmon = VerboseMonitor(1) solver.SetGenerationMonitor(stepmon) solver.Solve(wavy, ChangeOverGeneration(generations=50), \ strategy=strategy, CrossProbability=1.0, ScalingFactor=0.9, \ sigint_callback = plot_solution) solution = solver.Solution() return solution, solver
def de_solve(CF): solver = DifferentialEvolutionSolver(ND, NP) solver.enable_signal_handler() stepmon = VerboseMonitor(10,50) minrange = [-100., -100., -100.]; maxrange = [100., 100., 100.]; solver.SetRandomInitialPoints(min = minrange, max = maxrange) solver.SetStrictRanges(min = minrange, max = maxrange) solver.SetEvaluationLimits(generations=MAX_GENERATIONS) solver.SetGenerationMonitor(stepmon) solver.Solve(CF, termination=ChangeOverGeneration(generations=300),\ CrossProbability=0.5, ScalingFactor=0.5,\ sigint_callback=plot_sol) solution = solver.Solution() return solution, stepmon
def runme(): # instantiate the solver _solver = NelderMeadSimplexSolver(3) lb, ub = [0., 0., 0.], [10., 10., 10.] _solver.SetRandomInitialPoints(lb, ub) _solver.SetEvaluationLimits(1000) # add a monitor stream stepmon = VerboseMonitor(1) _solver.SetGenerationMonitor(stepmon) # configure the bounds _solver.SetStrictRanges(lb, ub) # configure stop conditions term = Or(VTR(), ChangeOverGeneration()) _solver.SetTermination(term) # add a periodic dump to an archive tmpfile = 'mysolver.pkl' _solver.SetSaveFrequency(10, tmpfile) # run the optimizer _solver.Solve(rosen) # get results x = _solver.bestSolution y = _solver.bestEnergy # load the saved solver solver = LoadSolver(tmpfile) #os.remove(tmpfile) # obligatory check that state is the same assert all(x == solver.bestSolution) assert y == solver.bestEnergy # modify the termination condition term = VTR(0.0001) solver.SetTermination(term) # run the optimizer solver.Solve(rosen) os.remove(tmpfile) # check the solver serializes _s = dill.dumps(solver) return dill.loads(_s)
def optimize(cost, _bounds, _constraints): from mystic.solvers import DifferentialEvolutionSolver2 from mystic.termination import ChangeOverGeneration as COG from mystic.strategy import Best1Exp from mystic.monitors import VerboseMonitor, Monitor from mystic.tools import random_seed #random_seed(123) stepmon = VerboseMonitor(2) #stepmon = Monitor() evalmon = Monitor() lb, ub = _bounds ndim = len(lb) solver = DifferentialEvolutionSolver2(ndim, npop) solver.SetRandomInitialPoints(min=lb, max=ub) solver.SetStrictRanges(min=lb, max=ub) solver.SetEvaluationLimits(maxiter, maxfun) solver.SetEvaluationMonitor(evalmon) solver.SetGenerationMonitor(stepmon) solver.SetConstraints(_constraints) tol = convergence_tol solver.Solve(cost,termination=COG(tol,ngen),strategy=Best1Exp, \ CrossProbability=crossover,ScalingFactor=percent_change) solved = solver.bestSolution #print("solved: %s" % solver.Solution()) func_max = MINMAX * solver.bestEnergy #NOTE: -solution assumes -Max #func_max = 1.0 + MINMAX*solver.bestEnergy #NOTE: 1-sol => 1-success = fail func_evals = solver.evaluations from mystic.munge import write_support_file write_support_file(stepmon, npts=npts) return solved, func_max, func_evals
def solve(measurements, method): """Find reasonable marker positions based on a set of measurements.""" print(method) marker_measurements = measurements if np.size(measurements) == 21: marker_measurements = measurements[(21 - 15) :] # m0 has known positions (0, 0, 0) # m1 has unknown x-position # All others have unknown xy-positions num_params = 0 + 1 + 2 + 2 + 2 + 2 bound = 400.0 lower_bound = [ 0.0, 0.0, 0.0, 0.0, 0.0, -bound, 0.0, -bound, 0.0, ] upper_bound = [ bound, bound, bound, bound, bound, bound, bound, bound, bound, ] def costx_no_nozzle(posvec): """Identical to cost_no_nozzle, except the shape of inputs""" positions = posvec2matrix_no_nozzle(posvec) return cost_no_nozzle(positions, marker_measurements) guess_0 = [0.0] * num_params intermediate_cost = 0.0 intermediate_solution = [] if method == "SLSQP": sol = scipy.optimize.minimize( costx_no_nozzle, guess_0, method="SLSQP", bounds=list(zip(lower_bound, upper_bound)), tol=1e-20, options={"disp": True, "ftol": 1e-40, "eps": 1e-10, "maxiter": 500}, ) intermediate_cost = sol.fun intermediate_solution = sol.x elif method == "L-BFGS-B": sol = scipy.optimize.minimize( costx_no_nozzle, guess_0, method="L-BFGS-B", bounds=list(zip(lower_bound, upper_bound)), options={"disp": True, "ftol": 1e-12, "gtol": 1e-12, "maxiter": 50000, "maxfun": 1000000}, ) intermediate_cost = sol.fun intermediate_solution = sol.x elif method == "PowellDirectionalSolver": from mystic.solvers import PowellDirectionalSolver from mystic.termination import Or, CollapseAt, CollapseAs from mystic.termination import ChangeOverGeneration as COG from mystic.monitors import VerboseMonitor from mystic.termination import VTR, And, Or solver = PowellDirectionalSolver(num_params) solver.SetRandomInitialPoints(lower_bound, upper_bound) solver.SetEvaluationLimits(evaluations=3200000, generations=100000) solver.SetTermination(Or(VTR(1e-25), COG(1e-10, 20))) solver.SetStrictRanges(lower_bound, upper_bound) solver.SetGenerationMonitor(VerboseMonitor(5)) solver.Solve(costx_no_nozzle) intermediate_cost = solver.bestEnergy intermediate_solution = solver.bestSolution elif method == "differentialEvolutionSolver": from mystic.solvers import DifferentialEvolutionSolver2 from mystic.monitors import VerboseMonitor from mystic.termination import VTR, ChangeOverGeneration, And, Or from mystic.strategy import Best1Exp, Best1Bin stop = Or(VTR(1e-18), ChangeOverGeneration(1e-9, 500)) npop = 3 stepmon = VerboseMonitor(100) solver = DifferentialEvolutionSolver2(num_params, npop) solver.SetEvaluationLimits(evaluations=3200000, generations=100000) solver.SetRandomInitialPoints(lower_bound, upper_bound) solver.SetStrictRanges(lower_bound, upper_bound) solver.SetGenerationMonitor(stepmon) solver.Solve( costx_no_nozzle, termination=stop, strategy=Best1Bin, ) intermediate_cost = solver.bestEnergy intermediate_solution = solver.bestSolution else: print("Method %s is not supported!" % method) sys.exit(1) print("Best intermediate cost: ", intermediate_cost) print("Best intermediate positions: \n%s" % posvec2matrix_no_nozzle(intermediate_solution)) if np.size(measurements) == 15: print("Got only 15 samples, so will not try to find nozzle position\n") return nozzle_measurements = measurements[: (21 - 15)] # Look for nozzle's xyz-offset relative to marker 0 num_params = 3 lower_bound = [ 0.0, 0.0, -bound, ] upper_bound = [bound, bound, 0.0] def costx_nozzle(posvec): """Identical to cost_nozzle, except the shape of inputs""" positions = posvec2matrix_nozzle(posvec, intermediate_solution) return cost_nozzle(positions, measurements) guess_0 = [0.0, 0.0, 0.0] final_cost = 0.0 final_solution = [] if method == "SLSQP": sol = scipy.optimize.minimize( costx_nozzle, guess_0, method="SLSQP", bounds=list(zip(lower_bound, upper_bound)), tol=1e-20, options={"disp": True, "ftol": 1e-40, "eps": 1e-10, "maxiter": 500}, ) final_cost = sol.fun final_solution = sol.x elif method == "L-BFGS-B": sol = scipy.optimize.minimize( costx_nozzle, guess_0, method="L-BFGS-B", bounds=list(zip(lower_bound, upper_bound)), options={"disp": True, "ftol": 1e-12, "gtol": 1e-12, "maxiter": 50000, "maxfun": 1000000}, ) final_cost = sol.fun final_solution = sol.x elif method == "PowellDirectionalSolver": from mystic.solvers import PowellDirectionalSolver from mystic.termination import Or, CollapseAt, CollapseAs from mystic.termination import ChangeOverGeneration as COG from mystic.monitors import VerboseMonitor from mystic.termination import VTR, And, Or solver = PowellDirectionalSolver(num_params) solver.SetRandomInitialPoints(lower_bound, upper_bound) solver.SetEvaluationLimits(evaluations=3200000, generations=100000) solver.SetTermination(Or(VTR(1e-25), COG(1e-10, 20))) solver.SetStrictRanges(lower_bound, upper_bound) solver.SetGenerationMonitor(VerboseMonitor(5)) solver.Solve(costx_nozzle) final_cost = solver.bestEnergy final_solution = solver.bestSolution elif method == "differentialEvolutionSolver": from mystic.solvers import DifferentialEvolutionSolver2 from mystic.monitors import VerboseMonitor from mystic.termination import VTR, ChangeOverGeneration, And, Or from mystic.strategy import Best1Exp, Best1Bin stop = Or(VTR(1e-18), ChangeOverGeneration(1e-9, 500)) npop = 3 stepmon = VerboseMonitor(100) solver = DifferentialEvolutionSolver2(num_params, npop) solver.SetEvaluationLimits(evaluations=3200000, generations=100000) solver.SetRandomInitialPoints(lower_bound, upper_bound) solver.SetStrictRanges(lower_bound, upper_bound) solver.SetGenerationMonitor(stepmon) solver.Solve( costx_nozzle, termination=stop, strategy=Best1Bin, ) final_cost = solver.bestEnergy final_solution = solver.bestSolution print("Best final cost: ", final_cost) print("Best final positions:") final = posvec2matrix_nozzle(final_solution, intermediate_solution)[1:] for num in range(0, 6): print( "{0: 8.3f} {1: 8.3f} {2: 8.3f} <!-- Marker {3} -->".format(final[num][0], final[num][1], final[num][2], num) )
def impose_valid(cutoff, model, guess=None, **kwds): """impose model validity on a given list of parameters w,x,y Optimization on w,x,y over the given bounds seeks sum(infeasibility) = 0. (this function is not ???-preserving) Inputs: cutoff -- maximum acceptable model invalidity |y - F(x')|; a single value model -- the model function, y' = F(x'), that approximates reality, y = G(x) guess -- the scenario providing an initial guess at validity, or a tuple of dimensions of the target scenario Additional Inputs: hausdorff -- norm; where if given, ytol = |y - F(x')| + |x - x'|/norm xtol -- acceptable pointwise graphical distance of model from reality tol -- acceptable optimizer termination before sum(infeasibility) = 0. bounds -- a tuple of sample bounds: bounds = (lower_bounds, upper_bounds) constraints -- a function that takes a flat list parameters x' = constraints(x) Outputs: pm -- a scenario with desired model validity Notes: xtol defines the n-dimensional base of a pilar of height cutoff, centered at each point. The region inside the pilar defines the space where a "valid" model must intersect. If xtol is not specified, then the base of the pilar will be a dirac at x' = x. This function performs an optimization to find a set of points where the model is valid. Here, tol is used to set the optimization termination for the sum(graphical_distances), while cutoff is used in defining the graphical_distance between x,y and x',F(x'). """ from numpy import sum as _sum, asarray from mystic.math.distance import graphical_distance, infeasibility, _npts if guess is None: message = "Requires a guess scenario, or a tuple of scenario dimensions." raise TypeError, message # get initial guess if hasattr(guess, 'pts'): # guess is a scenario pts = guess.pts # number of x guess = guess.flatten(all=True) else: pts = guess # guess is given as a tuple of 'pts' guess = None npts = _npts(pts) # number of Y # prepare bounds for solver bounds = kwds.pop('bounds', None) # if bounds are not set, use the default optimizer bounds if bounds is None: lower_bounds = []; upper_bounds = [] for n in pts: # bounds for n*x in each dimension (x2 due to weights) lower_bounds += [None]*n * 2 upper_bounds += [None]*n * 2 # also need bounds for npts*y values lower_bounds += [None]*npts upper_bounds += [None]*npts bounds = lower_bounds, upper_bounds bounds = asarray(bounds).T # plug in the 'constraints' function: param' = constraints(param) constraints = kwds.pop('constraints', None) # default is no constraints if not constraints: # if None (default), there are no constraints constraints = lambda x: x # 'wiggle room' tolerances ipop = kwds.pop('ipop', 10) #XXX: tune ipop (inner optimization)? imax = kwds.pop('imax', 10) #XXX: tune imax (inner optimization)? # tolerance for optimization on sum(y) tol = kwds.pop('tol', 0.0) # default npop = kwds.pop('npop', 20) #XXX: tune npop (outer optimization)? maxiter = kwds.pop('maxiter', 1000) #XXX: tune maxiter (outer optimization)? # if no guess was made, then use bounds constraints if guess is None: if npop: guess = bounds else: # fmin_powell needs a list params (not bounds) guess = [(a + b)/2. for (a,b) in bounds] # construct cost function to reduce sum(infeasibility) def cost(rv): """compute cost from a 1-d array of model parameters, where: cost = | sum( infeasibility ) | """ # converting rv to scenario points = scenario() points.load(rv, pts) # calculate infeasibility Rv = graphical_distance(model, points, ytol=cutoff, ipop=ipop, \ imax=imax, **kwds) v = infeasibility(Rv, cutoff) # converting v to E return _sum(v) #XXX: abs ? # construct and configure optimizer debug = False #!!! maxfun = 1e+6 crossover = 0.9; percent_change = 0.8 ftol = abs(tol); gtol = None #XXX: optimally, should be VTRCOG... if debug: print "lower bounds: %s" % bounds.T[0] print "upper bounds: %s" % bounds.T[1] # print "initial value: %s" % guess # use optimization to get model-valid points from mystic.solvers import diffev2, fmin_powell from mystic.monitors import Monitor, VerboseMonitor from mystic.strategy import Best1Bin, Best1Exp evalmon = Monitor(); stepmon = Monitor(); strategy = Best1Exp if debug: stepmon = VerboseMonitor(2) #!!! if npop: # use VTR results = diffev2(cost, guess, npop, ftol=ftol, gtol=gtol, bounds=bounds,\ maxiter=maxiter, maxfun=maxfun, constraints=constraints,\ cross=crossover, scale=percent_change, strategy=strategy,\ evalmon=evalmon, itermon=stepmon,\ full_output=1, disp=0, handler=False) else: # use VTR results = fmin_powell(cost, guess, ftol=ftol, gtol=gtol, bounds=bounds,\ maxiter=maxiter, maxfun=maxfun, constraints=constraints,\ evalmon=evalmon, itermon=stepmon,\ full_output=1, disp=0, handler=False) # repack the results pm = scenario() pm.load(results[0], pts) # params: w,x,y #if debug: print "final cost: %s" % results[1] if debug and results[2] >= maxiter: # iterations print "Warning: constraints solver terminated at maximum iterations" #func_evals = results[3] # evaluation return pm
def radius(model, point, ytol=0.0, xtol=0.0, ipop=None, imax=None): """graphical distance between a single point x,y and a model F(x')""" # given a single point x,y: find the radius = |y - F(x')| + delta # radius is just a minimization over x' of |y - F(x')| + delta # where we apply a constraints function (of box constraints) of # |x - x'| <= xtol (for each i in x) # # if hausdorff = some iterable, delta = |x - x'|/hausdorff # if hausdorff = True, delta = |x - x'|/spread(x); using the dataset range # if hausdorff = False, delta = 0.0 # # if ipop, then DE else Powell; ytol is used in VTR(ytol) # and will terminate when cost <= ytol x,y = _get_xy(point) y = asarray(y) # catch cases where yptp or y will cause issues in normalization #if not isfinite(yptp): return 0.0 #FIXME: correct? shouldn't happen #if yptp == 0: from numpy import inf; return inf #FIXME: this is bad # build the cost function if hausdorff: # distance in all directions def cost(rv): '''cost = |y - F(x')| + |x - x'| for each x,y (point in dataset)''' _y = model(rv) if not isfinite(_y): return abs(_y) errs = seterr(invalid='ignore', divide='ignore') # turn off warning z = abs((asarray(x) - rv)/ptp) # normalize by range m = abs(y - _y)/yptp # normalize by range seterr(invalid=errs['invalid'], divide=errs['divide']) # turn on warning return m + sum(z[isfinite(z)]) else: # vertical distance only def cost(rv): '''cost = |y - F(x')| for each x,y (point in dataset)''' return abs(y - model(rv)) if debug: print("rv: %s" % str(x)) print("cost: %s" % cost(x)) # if xtol=0, radius is difference in x,y and x,F(x); skip the optimization try: if not imax or not max(xtol): #iterables return cost(x) except TypeError: if not xtol: #non-iterables return cost(x) # set the range constraints xtol = asarray(xtol) bounds = list(zip( x - xtol, x + xtol )) if debug: print("lower: %s" % str(zip(*bounds)[0])) print("upper: %s" % str(zip(*bounds)[1])) # optimize where initially x' = x stepmon = Monitor() if debug: stepmon = VerboseMonitor(1) #XXX: edit settings? MINMAX = 1 #XXX: confirm MINMAX=1 is minimization ftol = ytol gtol = None # use VTRCOG if ipop: results = diffev2(cost, bounds, ipop, ftol=ftol, gtol=gtol, \ itermon = stepmon, maxiter=imax, bounds=bounds, \ full_output=1, disp=0, handler=False) else: results = fmin_powell(cost, x, ftol=ftol, gtol=gtol, \ itermon = stepmon, maxiter=imax, bounds=bounds, \ full_output=1, disp=0, handler=False) #solved = results[0] # x' func_opt = MINMAX * results[1] # cost(x') if debug: print("solved: %s" % results[0]) print("cost: %s" % func_opt) # get the minimum distance |y - F(x')| return func_opt
func_max = -solver.bestEnergy return solved, func_max if __name__ == '__main__': from mystic.monitors import Monitor, VerboseMonitor, LoggingMonitor from mystic.monitors import VerboseLoggingMonitor #monitor = Monitor() #monitor = Monitor(all=True) #monitor = Monitor(all=False) #monitor = VerboseMonitor(1,1) #monitor = VerboseMonitor(1,1, all=True) #monitor = VerboseMonitor(1,1, all=False) #monitor = VerboseMonitor(0,1) monitor = VerboseMonitor(1, 0) #monitor = LoggingMonitor(1) #monitor = LoggingMonitor(1, all=True) #monitor = LoggingMonitor(1, all=False) #monitor = VerboseLoggingMonitor(1) #monitor = VerboseLoggingMonitor(0,1) #test0(monitor) #test1(monitor) test2(monitor) # GenerationMonitor works like test0 #test2(monitor, diffenv=False) # (to make like test1, add enclosing []) #test2(monitor, diffenv=True) # these are for "MonitorPlotter(s)"; need to adapt log.py plotters for test1 write_support_file(monitor, 'paramlog1.py') # plot with 'support_*.py' #write_converge_file(monitor,'paramlog2.py') #XXX: no existing plotters?
def func(x): curve = func_value(x[0:3]) return -(sum(np.dot(curve, production)) - Q + x[3]) objective = lambda x: sum(np.dot(x[0:3], C)) + 1000 * x[3] constraint = lambda x: func(x) @quadratic_inequality(constraint) def penalty(x): return 0.0 mon = VerboseMonitor(50) solution = diffev2(objective, x0, penalty=penalty, bounds=bounds, itermon=mon, gtol=100, maxiter=1000, maxfun=10000, npop=40) print(solution) mon = VerboseMonitor(50) solution = fmin_powell(objective, x0, penalty=penalty,
def impose_feasible(cutoff, data, guess=None, **kwds): """impose shortness on a given list of parameters w,x,y. Optimization on w,x,y over the given bounds seeks sum(infeasibility) = 0. (this function is not ???-preserving) Inputs: cutoff -- maximum acceptable deviation from shortness data -- a dataset of observed points (these points are 'static') guess -- the scenario providing an initial guess at feasibility, or a tuple of dimensions of the target scenario Additional Inputs: tol -- acceptable optimizer termination before sum(infeasibility) = 0. bounds -- a tuple of sample bounds: bounds = (lower_bounds, upper_bounds) constraints -- a function that takes a flat list parameters x' = constraints(x) Outputs: pm -- a scenario with desired shortness """ from numpy import sum, asarray from mystic.math.legacydata import dataset from mystic.math.distance import lipschitz_distance, infeasibility, _npts if guess is None: message = "Requires a guess scenario, or a tuple of scenario dimensions." raise TypeError, message # get initial guess if hasattr(guess, 'pts'): # guess is a scenario pts = guess.pts # number of x guess = guess.flatten(all=True) else: pts = guess # guess is given as a tuple of 'pts' guess = None npts = _npts(pts) # number of Y long_form = len(pts) - list(pts).count(2) # can use '2^K compressed format' # prepare bounds for solver bounds = kwds.pop('bounds', None) # if bounds are not set, use the default optimizer bounds if bounds is None: lower_bounds = []; upper_bounds = [] for n in pts: # bounds for n*x in each dimension (x2 due to weights) lower_bounds += [None]*n * 2 upper_bounds += [None]*n * 2 # also need bounds for npts*y values lower_bounds += [None]*npts upper_bounds += [None]*npts bounds = lower_bounds, upper_bounds bounds = asarray(bounds).T # plug in the 'constraints' function: param' = constraints(param) # constraints should impose_mean(y,w), and possibly sum(weights) constraints = kwds.pop('constraints', None) # default is no constraints if not constraints: # if None (default), there are no constraints constraints = lambda x: x _self = kwds.pop('with_self', True) # default includes self in shortness if _self is not False: _self = True # tolerance for optimization on sum(y) tol = kwds.pop('tol', 0.0) # default npop = kwds.pop('npop', 20) #XXX: tune npop? maxiter = kwds.pop('maxiter', 1000) #XXX: tune maxiter? # if no guess was made, then use bounds constraints if guess is None: if npop: guess = bounds else: # fmin_powell needs a list params (not bounds) guess = [(a + b)/2. for (a,b) in bounds] # construct cost function to reduce sum(lipschitz_distance) def cost(rv): """compute cost from a 1-d array of model parameters, where: cost = | sum(lipschitz_distance) | """ _data = dataset() _pm = scenario() _pm.load(rv, pts) # here rv is param: w,x,y if not long_form: positions = _pm.select(*range(npts)) else: positions = _pm.positions _data.load( data.coords, data.values ) # LOAD static if _self: _data.load( positions, _pm.values ) # LOAD dynamic _data.lipschitz = data.lipschitz # LOAD L Rv = lipschitz_distance(_data.lipschitz, _pm, _data, tol=cutoff, **kwds) v = infeasibility(Rv, cutoff) return abs(sum(v)) # construct and configure optimizer debug = False #!!! maxfun = 1e+6 crossover = 0.9; percent_change = 0.9 ftol = abs(tol); gtol = None if debug: print "lower bounds: %s" % bounds.T[0] print "upper bounds: %s" % bounds.T[1] # print "initial value: %s" % guess # use optimization to get feasible points from mystic.solvers import diffev2, fmin_powell from mystic.monitors import Monitor, VerboseMonitor from mystic.strategy import Best1Bin, Best1Exp evalmon = Monitor(); stepmon = Monitor(); strategy = Best1Exp if debug: stepmon = VerboseMonitor(10) #!!! if npop: # use VTR results = diffev2(cost, guess, npop, ftol=ftol, gtol=gtol, bounds=bounds,\ maxiter=maxiter, maxfun=maxfun, constraints=constraints,\ cross=crossover, scale=percent_change, strategy=strategy,\ evalmon=evalmon, itermon=stepmon,\ full_output=1, disp=0, handler=False) else: # use VTR results = fmin_powell(cost, guess, ftol=ftol, gtol=gtol, bounds=bounds,\ maxiter=maxiter, maxfun=maxfun, constraints=constraints,\ evalmon=evalmon, itermon=stepmon,\ full_output=1, disp=0, handler=False) # repack the results pm = scenario() pm.load(results[0], pts) # params: w,x,y #if debug: print "final cost: %s" % results[1] if debug and results[2] >= maxiter: # iterations print "Warning: constraints solver terminated at maximum iterations" #func_evals = results[3] # evaluation return pm
# Copyright (c) 1997-2016 California Institute of Technology. # Copyright (c) 2016-2018 The Uncertainty Quantification Foundation. # License: 3-clause BSD. The full license text is available at: # - https://github.com/uqfoundation/mystic/blob/master/LICENSE from mystic.models import rosen from mystic.solvers import * from mystic.termination import VTRChangeOverGeneration from mystic.monitors import VerboseMonitor, Monitor from mystic.tools import random_seed random_seed(123) lb, ub = [-100.] * 3, [100] * 3 interval = None if interval: _stepmon = VerboseMonitor(interval) else: _stepmon = Monitor() _term = VTRChangeOverGeneration(generations=200) _solver = DifferentialEvolutionSolver(3, 20) #40) _solver.SetRandomInitialPoints(lb, ub) _solver.SetStrictRanges(lb, ub) _solver.SetTermination(_term) _solver.SetGenerationMonitor(_stepmon) _solver.SetEvaluationLimits(100, 1000) _solver.Solve(rosen) _energy = _solver.bestEnergy _solution = _solver.bestSolution _population = _solver.population
from mystic.solvers import fmin_powell # Rosenbrock function from mystic.models import rosen # tools from mystic.monitors import VerboseMonitor if __name__ == '__main__': print("Powell's Method") print("===============") # initial guess x0 = [0.8, 1.2, 0.7] # define constraints function def constraints(x): # constrain the last x_i to be the same value as the first x_i x[-1] = x[0] return x # configure monitor stepmon = VerboseMonitor(1) # use Powell's method to minimize the Rosenbrock function solution = fmin_powell(rosen, x0, constraints=constraints, itermon=stepmon) print(solution) # end of file
def impose_expectation(param, f, npts, bounds=None, weights=None, **kwds): """impose a given expextation value (m +/- D) on a given function f. Optimization on f over the given bounds seeks a mean 'm' with deviation 'D'. (this function is not 'mean-, range-, or variance-preserving') Inputs: param -- a tuple of target parameters: param = (mean, deviation) f -- a function that takes a list and returns a number npts -- a tuple of dimensions of the target product measure bounds -- a tuple of sample bounds: bounds = (lower_bounds, upper_bounds) weights -- a list of sample weights Additional Inputs: constraints -- a function that takes a nested list of N x 1D discrete measure positions and weights x' = constraints(x, w) npop -- size of the trial solution population maxiter -- number - the maximum number of iterations to perform maxfun -- number - the maximum number of function evaluations Outputs: samples -- a list of sample positions For example: >>> # provide the dimensions and bounds >>> nx = 3; ny = 2; nz = 1 >>> x_lb = [10.0]; y_lb = [0.0]; z_lb = [10.0] >>> x_ub = [50.0]; y_ub = [9.0]; z_ub = [90.0] >>> >>> # prepare the bounds >>> lb = (nx * x_lb) + (ny * y_lb) + (nz * z_lb) >>> ub = (nx * x_ub) + (ny * y_ub) + (nz * z_ub) >>> >>> # generate a list of samples with mean +/- dev imposed >>> mean = 2.0; dev = 0.01 >>> samples = impose_expectation((mean,dev), f, (nx,ny,nz), (lb,ub)) >>> >>> # test the results by calculating the expectation value for the samples >>> expectation(f, samples) >>> 2.00001001012246015 """ # param[0] is the target mean # param[1] is the acceptable deviation from the target mean # FIXME: the following is a HACK to recover from lost 'weights' information # we 'mimic' discrete measures using the product measure weights # plug in the 'constraints' function: samples' = constrain(samples, weights) constrain = None # default is no constraints if 'constraints' in kwds: constrain = kwds['constraints'] if not constrain: # if None (default), there are no constraints constraints = lambda x: x else: #XXX: better to use a standard "xk' = constrain(xk)" interface ? def constraints(rv): coords = _pack(_nested(rv, npts)) coords = zip(*coords) # 'mimic' a nested list coords = constrain(coords, [weights for i in range(len(coords))]) coords = zip(*coords) # revert back to a packed list return _flat(_unpack(coords, npts)) # construct cost function to reduce deviation from expectation value def cost(rv): """compute cost from a 1-d array of model parameters, where: cost = | E[model] - m |**2 """ # from mystic.math.measures import _pack, _nested, expectation samples = _pack(_nested(rv, npts)) Ex = expectation(f, samples, weights) return (Ex - param[0])**2 # if bounds are not set, use the default optimizer bounds if not bounds: lower_bounds = [] upper_bounds = [] for n in npts: lower_bounds += [None] * n upper_bounds += [None] * n else: lower_bounds, upper_bounds = bounds # construct and configure optimizer debug = kwds['debug'] if 'debug' in kwds else False npop = kwds.pop('npop', 200) maxiter = kwds.pop('maxiter', 1000) maxfun = kwds.pop('maxfun', 1e+6) crossover = 0.9 percent_change = 0.9 def optimize(cost, (lb, ub), tolerance, _constraints): from mystic.solvers import DifferentialEvolutionSolver2 from mystic.termination import VTR from mystic.strategy import Best1Exp from mystic.monitors import VerboseMonitor, Monitor from mystic.tools import random_seed if debug: random_seed(123) evalmon = Monitor() stepmon = Monitor() if debug: stepmon = VerboseMonitor(10) ndim = len(lb) solver = DifferentialEvolutionSolver2(ndim, npop) solver.SetRandomInitialPoints(min=lb, max=ub) solver.SetStrictRanges(min=lb, max=ub) solver.SetEvaluationLimits(maxiter, maxfun) solver.SetEvaluationMonitor(evalmon) solver.SetGenerationMonitor(stepmon) solver.Solve(cost,termination=VTR(tolerance),strategy=Best1Exp, \ CrossProbability=crossover,ScalingFactor=percent_change, \ constraints = _constraints) solved = solver.Solution() diameter_squared = solver.bestEnergy func_evals = len(evalmon) return solved, diameter_squared, func_evals
N, x0 = x0.split("*") constrain = "{x0} = ({rhs} - ({xN}))/{N}".format(x0=x0, xN=xN, N=N, rhs=rhs) #NOTE: end HACK (as mystic.symbolic.solve takes __forever__) constrain = constraint(solvers(constrain)) #constrain = constraint(solvers(solve(constrain))) from mystic import suppressed @suppressed(1e-2) def conserve(x): return constrain(x) from mystic.monitors import VerboseMonitor mon = VerboseMonitor(10) # solve the dual for alpha from mystic.solvers import DifferentialEvolutionSolver as DESolver from mystic.termination import Or, ChangeOverGeneration, CollapseAt ndim = len(lb) npop = nx * 3 stop = Or(ChangeOverGeneration(1e-8, 200), CollapseAt(0.0)) solver = DESolver(ndim, npop) solver.SetRandomInitialPoints(min=lb, max=_b) solver.SetStrictRanges(min=lb, max=ub) solver.SetGenerationMonitor(mon) solver.SetConstraints(conserve) solver.SetTermination(stop) solver.Solve(objective, ExtraArgs=(Q, b), disp=1) alpha = solver.bestSolution
""" from mystic.solvers import DifferentialEvolutionSolver2 from mystic.monitors import VerboseMonitor, Monitor from mystic.termination import ChangeOverGeneration as COG # kwds for solver opts = dict(termination=COG(1e-6, 40), CrossProbability=0.9, ScalingFactor=0.9) param = dict( solver=DifferentialEvolutionSolver2, npop=10, #XXX:npop maxiter=1000, maxfun=1e+6, x0=None, # use RandomInitialPoints nested=None, # don't use SetNested pool=None, # don't use SetMapper stepmon=VerboseMonitor(1, label='output'), # monitor config evalmon=Monitor(), # monitor config (re-initialized in solve) # kwds to pass directly to Solve(objective, **opt) opts=opts, ) from mystic.math.discrete import product_measure from mystic.math import almostEqual as almost from mystic.constraints import and_, integers from mystic.coupler import outer # lower and upper bound for parameters and weights xlb = (20.0, 0.0, 2.1) xub = (150.0, 30.0, 2.8) wlb = (0, 1, 1) wub = (1, 1, 1)
ND = 9 NP = 80 MAX_GENERATIONS = NP * NP NNODES = NP // 5 seed = 321 if __name__ == '__main__': from pathos.helpers import freeze_support freeze_support() # help Windows use multiprocessing def print_solution(func): print(poly1d(func)) return psow = VerboseMonitor(10) ssow = VerboseMonitor(10) random_seed(seed) print("first sequential...") solver = DifferentialEvolutionSolver2(ND, NP) solver.SetRandomInitialPoints(min=[-100.0] * ND, max=[100.0] * ND) solver.SetEvaluationLimits(generations=MAX_GENERATIONS) solver.SetGenerationMonitor(ssow) solver.Solve(ChebyshevCost, VTR(0.01), strategy=Best1Exp, \ CrossProbability=1.0, ScalingFactor=0.9, disp=1) print("") print_solution(solver.bestSolution) random_seed(seed) print("\n and now parallel...")
def optimize(self, optversion, method = 'diff-ev', gtol = 5000, positive_weights: bool = True, x0 = None, bs0 = None, bounds = [0., 1.], noisebiasconstr = False, fb = 1., inv_variance = False, verbose = True, noiseparameter = 1.): ''' Methods: diff-ev, SLSQP ''' if verbose: print(f'Start optimization with {method}') if inv_variance: print('Using combined inverse variance weights') if x0 is None: x0 = [] if self.lenestimators == 2: v = np.random.rand(1)/2 elif self.lenestimators == 3: v = np.random.rand(2)/2 elif self.lenestimators == 4: v = np.random.rand(3)/2 for a in v: x0 += [a] x0 += [1.-np.sum(v)] x0 = np.array(x0*int(self.nbins)) if bs0 is None: bs0 = np.ones(int(self.nbins)) norma = self.integerate_discrete(bs0, self.ells_selected) bs0 /= norma dims = (self.lenestimators+1) if not inv_variance else self.lenestimators bnds = [(bounds[0], bounds[1]) for i in range(dims*self.nbins)] bnds = tuple(bnds) if inv_variance: x0 = x0 else: x0 = np.append(x0, bs0) #if positive_weights: # cons = ({'type': 'eq', 'fun': self.get_constraint()}, {'type': 'ineq', 'fun': self.get_constraint_ineq()}) #else: # cons = ({'type': 'eq', 'fun': self.get_constraint()}) weights_name = optversion['weights_name'] if verbose: print(f'Doing for {weights_name}') sum_biases_squared = optversion['sum_biases_squared'] abs_biases = optversion['abs_biases'] bias_squared = optversion['bias_squared'] if abs_biases: prepare = lambda x: abs(x) else: prepare = lambda x: x f, noisef, biasf = self.get_f_n_b(self.ells_selected, self.theory_selected, self.theta_selected, prepare(self.biases_selected), sum_biases_squared = sum_biases_squared, bias_squared = bias_squared, fb = fb, inv_variance = inv_variance, noiseparameter = noiseparameter) self.f = f self.noisef = noisef self.biasf = biasf extra_constraint = lambda x: abs(self.noisef(np.array(x))-self.biasf(np.array(x))) def constraint_eq(x): x = np.array(x) a = self.get_a(x, inv_variance) a[:, -1] = 1-np.sum(a[:, :-1], axis = 1) if not inv_variance: x[:-self.nbins] = a.flatten() else: x = a.flatten() return x def penalty1(x): x = np.array(x) b = x[-self.nbins:] res = self.integerate_discrete(b, self.ells_selected) return 1-res k = 1e20 if noisebiasconstr: gtol = gtol @quadratic_equality(condition=penalty1, k = k) @quadratic_equality(condition=extra_constraint, k = k) def penalty(x): return 0.0 else: gtol = gtol @quadratic_equality(condition=penalty1, k = k) def penalty(x): return 0.0 if inv_variance: penalty = None if noisebiasconstr: @quadratic_equality(condition=extra_constraint, k = k) def penalty(x): return 0.0 mon = VerboseMonitor(100) func = lambda x: f(np.array(x)) result = my.diffev(func, x0, npop = 10*len(list(bnds)), bounds = bnds, ftol = 1e-11, gtol = gtol, maxiter = 1024**3, maxfun = 1024**3, constraints = constraint_eq, penalty = penalty, full_output=True, itermon=mon) result = Res(result[0], self.ells_selected) self.result = result ws = self.get_weights(result.x, inv_variance, verbose = verbose) weights_per_l = self.get_final_variance_weights(result.x, self.ells_selected, self.theory_selected, self.theta_selected, inv_variance) result.set_weights(tuple(list(ws)+[weights_per_l])) self.monitor = mon return result