source: branches/decorate/restarts.py @ 855

Revision 855, 5.2 KB checked in by mmckerns, 5 months ago (diff)

updated copyright to 2016

Line 
1#!/usr/bin/env python
2#
3# Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
4# Copyright (c) 2012-2016 California Institute of Technology.
5# License: 3-clause BSD.  The full license text is available at:
6#  - http://mmckerns.github.io/project/mystic/browser/mystic/LICENSE
7
8def sumt(cost, solver, term, eps = 1e-4, max_SUMT_iters = 10, **kwds):
9
10    from mystic.tools import Null
11    from numpy import inf
12    # standard solver config
13    StepMonitor=kwds.get('StepMonitor', Null)
14    EvaluationMonitor=kwds.get('EvaluationMonitor', Null)
15    sigint_callback=kwds.get('sigint_callback', None)
16    disp = kwds.get('disp',False)
17
18    # other config
19    randomstate = kwds.get('randomstate',None)
20
21    # SUMT penalty restart
22    F_values = []
23    E_values = []
24    x_values = []
25    total_iterations = 0.
26    total_energy_history = []
27    exitflag = 0
28    # The outer SUMT for loop. In each iteration, an optimization will be
29    # performed.
30    for q in range(max_SUMT_iters):
31        if q == 0:
32            x0 = solver.population[0]
33        else:
34            x0 = x_values[-1]
35
36        if disp:
37            print 'SUMT iteration %d: x = ' % q, x0
38
39        if randomstate:
40            import random
41            random.setstate(randomstate)
42
43        # 'Clear' some of the attributes of the solver
44        solver.population = [[0.0 for i in range(solver.nDim)] for j in range(solver.nPop)]
45       #solver.generations = 0
46        solver.bestEnergy = None
47        solver.bestSolution = None
48        solver.trialSolution = [0.0] * solver.nDim
49        solver.popEnergy = [solver._init_popEnergy] * solver.nPop
50       #solver.energy_history = []
51
52        # individual solver __init__
53        if solver.__class__.__name__ == 'NelderMeadSimplexSolver':
54            simplex = solver.nDim + 1
55            solver.popEnergy = [solver._init_popEnergy] * simplex
56            solver.population = [[0.0 for i in range(solver.nDim)] for j in range(simplex)]
57        elif solver.__class__.__name__ == 'PowellDirectionalSolver':
58            solver._direc = None
59        elif solver.__class__.__name__ in ['DifferentialEvolutionSolver','DifferentialEvolutionSolver2']:
60            solver.genealogy = [ [] for j in range(solver.nPop)]
61        else: pass
62
63        # Perform the 'inner' optimization
64        solver.SetInitialPoints(x0)
65        solver.SetEvaluationMonitor(EvaluationMonitor)
66        solver.SetGenerationMonitor(StepMonitor)
67        solver.Solve(cost, term, sigint_callback=sigint_callback, **kwds)
68        x = solver.bestSolution
69        y = solver.bestEnergy
70
71        # When a user sets maxiter and maxfun, that is actually the maxiter
72        # and maxfun *each* SUMT iteration. However, it is difficult to check
73        # total maxfun and maxiter each SUMT iteration because then what
74        # would the inner maxiter and maxfun be? Better to just leave maxiter
75        # and maxfun as limits for each inner optimization...
76        total_iterations += solver.generations
77        total_energy_history += solver.energy_history
78
79        F_values.append(cost(x)) #XXX: cost = no penalty; y = penalty
80        E_values.append(y)
81        x_values.append(x)
82
83        # Update penalty parameters
84        solver._penalty.store(x) #XXX: may want to combine store with iter
85
86        # break due to the signal handler
87        if solver._EARLYEXIT:
88            exitflag = 3
89            break
90
91        # breaking if constraints satisfied may cause premature exit. so don't
92        # if False:
93        #     exitflag = 1
94        #     break
95
96        # break if cost(x) not improving after SUMT loop
97        if q != 0:
98            if abs(F_values[q] - F_values[q-1]) <= eps: #XXX: F or E ?
99                exitflag = 2
100                break
101            # break for no improvement in x's after SUMT loop
102            #if linalg.norm(asarray(x_values[q])-asarray(x_values[q-1])) <= eps:
103            #    exitflag = 4
104            #    break
105
106        # Update penalty parameters
107        solver._penalty.iter()   #XXX: may need 'assurance' to have iter()
108       
109    if disp:
110        if exitflag == 0:
111            print "SUMT exited because maximum number of SUMT iterations reached."
112        elif exitflag == 1:
113            print "SUMT exited because constraints were satisfied."
114        elif exitflag == 2:
115            print "SUMT exited because F values reached tolerance for improving."
116        elif exitflag == 3:
117            print "SUMT exited because signal handler 'exit' was selected."
118        #elif exitflag == 4:
119        #    print "SUMT exited because x values reached tolerance for improving."   
120        else:
121            print "SUMT exited for other reason."
122        print "%d SUMT iterations were performed." % (q + 1)
123
124    # Return the last solver, which contains all of the important information
125    # First modify the solver to include total data.
126   #solver.generations = total_iterations
127   #solver.energy_history = total_energy_history
128
129    #XXX solver.bestEnergy is not exactly cost(solver.bestSolution),
130    # since it is cost(bestSolution) with a penalty. Compensate for that
131    # here? Then, it is inconsistent with solver.energy_history, which
132    # also records cost(bestSolution) with a penalty....
133    #solver.bestEnergy = cost(solver.bestSolution)
134    return solver
135
Note: See TracBrowser for help on using the repository browser.