def _reset(self):
		self._p0 = sstruct([(k,v) for k,v in self._allitems() if k in self._free])
		flat_p0_free = flatten(self._p0, include=self._free)
		self._np = flat_p0_free.size
		self._f0 = self.eval()
		self._scalar = not hasattr(self._f0, '__len__')
		flat_f0_free = flatten(self._f0)
		self._nf = flat_f0_free.size

		try: self.deriv(); raise Exception()
		except NoSubclassMethod: self._deriv = None
		except:
			self._deriv = sstruct()
			for k,v in self._allitems():
				if k in self._free: self._deriv._setfield(k, v * 0.0)

		try: self.dderiv(); raise Exception()
		except NoSubclassMethod: self._dderiv = None
		except:
			self._dderiv = sstruct()
			for k,v in self._allitems():
				if k in self._free: self._dderiv._setfield(k, v * 0.0)

		try: self.hessian(); raise Exception()
		except NoSubclassMethod: self._hessian = None
		except:
			siz = [self._np, self._np]
			self._hessian = numpy.matrix(siz, dtype=numpy.float64)  # TODO(HHH): use of Hessians currently assumes scalar zero-order function output

		self.reset() # call developer's subclass method
		return flat_p0_free
Beispiel #2
0
    def _reset(self):
        self._p0 = sstruct([(k, v) for k, v in self._allitems()
                            if k in self._free])
        flat_p0_free = flatten(self._p0, include=self._free)
        self._np = flat_p0_free.size
        self._f0 = self.eval()
        self._scalar = not hasattr(self._f0, '__len__')
        flat_f0_free = flatten(self._f0)
        self._nf = flat_f0_free.size

        try:
            self.deriv()
            raise Exception()
        except NoSubclassMethod:
            self._deriv = None
        except:
            self._deriv = sstruct()
            for k, v in self._allitems():
                if k in self._free: self._deriv._setfield(k, v * 0.0)

        try:
            self.dderiv()
            raise Exception()
        except NoSubclassMethod:
            self._dderiv = None
        except:
            self._dderiv = sstruct()
            for k, v in self._allitems():
                if k in self._free: self._dderiv._setfield(k, v * 0.0)

        try:
            self.hessian()
            raise Exception()
        except NoSubclassMethod:
            self._hessian = None
        except:
            siz = [self._np, self._np]
            self._hessian = numpy.matrix(
                siz, dtype=numpy.float64
            )  # TODO(HHH): use of Hessians currently assumes scalar zero-order function output

        self.reset()  # call developer's subclass method
        return flat_p0_free
	def chgrad(self, plot=False, **kwargs):
		
		for k,v in kwargs.items():
			self._setfield(k,v)
	
		pflat = self._reset()	
		out = sstruct()
		out.params = self._p0.copy()
		out._setfield('f.exact', self._f(pflat, force1D=True))
		out._setfield('df.exact', self._df(pflat, force2D=True))
		out._setfield('df.approx', out.df.exact * numpy.nan)

		try: out._setfield('ddf.exact', self._ddf(pflat, force2D=True))
		except NoSubclassMethod: do_ddf = False
		else: do_ddf = True; out._setfield('ddf.approx', out.ddf.exact * numpy.nan)

		try: out._setfield('H.exact', self._H(pflat))
		except NoSubclassMethod: do_hessian = False
		else: do_hessian = True; out._setfield('H.approx', out.H.exact * numpy.nan)
				
		fdelta = 1e-4
		e = fdelta * abs(pflat)
		e = numpy.fmax(1e-12, e)		
		keepgoing = (e > 0) # all True to start

		rpt = 0
		while keepgoing.any():
			rpt += 1	
			for iparam in range(self._np):	
				mask = pflat * 0.0
				mask.flat[iparam] = 0.5	
				p_below = pflat - e * mask
				p_above = pflat + e * mask				
				f_below = self._f(p_below)
				f_above = self._f(p_above)							
				adfj = (f_above - f_below) / e[iparam]
				out.df.approx[:, iparam] = adfj  # TODO(III): store data from multiple rpts?
				if do_hessian or do_ddf:
					df_below = self._df(p_below)
					df_above = self._df(p_above)
					addfj = (df_above - df_below) / e[iparam]			
				if do_ddf:
					out.ddf.approx[:, iparam] = addfj[:, iparam] # TODO(III): store data from multiple rpts?			
				if do_hessian:
					out.H.approx[:, iparam].flat = addfj.flat # TODO(III): store data from multiple rpts?			
				converged = True      # TODO(III): could check for convergence here. currently, only one iteration is performed
				if converged: keepgoing[iparam] = False
			e[keepgoing] /= 2
		
		unflatten(self, pflat, include=self._free)
		self._reset()
		out.plabels = ['p'+x for x in flatten(self, include=self._free, labels=True)]
		out.flabels = ['f'+x for x in flatten(self.eval(), include=self._free, labels=True)]
		
		fields = ['df', 'ddf', 'H']
		for k in fields:
			v = out._getfield(k, None)
			if v == None: continue
			v.abserr = abs(v.exact-v.approx)
			v.maxabserr = v.abserr.max()
			v.propabserr = v.abserr / numpy.fmax(abs(v.approx), 1e-13)
			v.maxpropabserr = v.propabserr.max()
		
		if plot:
			import Plotting
			pylab = Plotting.load_pylab()
		
			fields = ['df', 'ddf', 'H']
			labels = {'df':(out.flabels,out.plabels, 'd%s / d%s'),
			          'ddf':(out.flabels,out.plabels, 'd^2%s / d%s^2'),
			          'H':(out.plabels,out.plabels, 'df/(d%s)(d%s)'),
			}
			got = dict([(k,k in out._fields) for k in fields])			
			nplots = sum(got.values())
			for i,k in enumerate(fields):
				v = out._getfield(k, None)
				if v == None: continue
				if nplots > 1: pylab.subplot(1, nplots, i+1)
				x = abs(v.approx.flatten())
				y = v.abserr.flatten()
				both0 = numpy.logical_and(x==0.0, y==0.0)
				x[both0] = numpy.nan
				y[both0] = numpy.nan
				x[x==0.0] = 1e-13
				y[y==0.0] = 1e-13
				x = numpy.log10(x)
				y = numpy.log10(y)
				pylab.cla()
				ax = pylab.gca()
				ax.indicator, = pylab.plot([numpy.nan,numpy.nan],[numpy.nan,numpy.nan], color=(1,0,1), linewidth=2)
				v.handles = pylab.plot(numpy.expand_dims(x,0), numpy.expand_dims(y,0), linestyle='None', marker='o', markersize=10, picker=5)
				lab = labels[k]
				for j,h in enumerate(v.handles):
					subs = numpy.unravel_index(j, v.approx.shape)
					h.txt = (lab[2]+'\nprop. abs. err. = %g') % (lab[0][subs[0]], lab[1][subs[1]], v.propabserr.flat[j])
				ax.set_xlabel('log10 of abs approx value')
				ax.set_ylabel('log10 of abs error')
				ax.grid(True)
			
			def onpick(evt):
				h = evt.artist
				x,y = h.get_xdata(), h.get_ydata()
				ax = h.axes
				ax.set_title(h.txt)
				ind = ax.indicator
				xl,yl = numpy.asarray(ax.get_xlim()),numpy.asarray(ax.get_ylim())
				ind.set_xdata([x.mean(), xl.mean()])
				ind.set_ydata([y.mean(), yl.max() + numpy.diff(yl) * 0.01])
				ind.set_clip_on(False)
				ind.set_color(h.get_color())
				pylab.draw()
				
			pylab.gcf().canvas.mpl_connect('pick_event', onpick)
			pylab.draw()
			
		return out
Beispiel #4
0
    def chgrad(self, plot=False, **kwargs):

        for k, v in kwargs.items():
            self._setfield(k, v)

        pflat = self._reset()
        out = sstruct()
        out.params = self._p0.copy()
        out._setfield('f.exact', self._f(pflat, force1D=True))
        out._setfield('df.exact', self._df(pflat, force2D=True))
        out._setfield('df.approx', out.df.exact * numpy.nan)

        try:
            out._setfield('ddf.exact', self._ddf(pflat, force2D=True))
        except NoSubclassMethod:
            do_ddf = False
        else:
            do_ddf = True
            out._setfield('ddf.approx', out.ddf.exact * numpy.nan)

        try:
            out._setfield('H.exact', self._H(pflat))
        except NoSubclassMethod:
            do_hessian = False
        else:
            do_hessian = True
            out._setfield('H.approx', out.H.exact * numpy.nan)

        fdelta = 1e-4
        e = fdelta * abs(pflat)
        e = numpy.fmax(1e-12, e)
        keepgoing = (e > 0)  # all True to start

        rpt = 0
        while keepgoing.any():
            rpt += 1
            for iparam in range(self._np):
                mask = pflat * 0.0
                mask.flat[iparam] = 0.5
                p_below = pflat - e * mask
                p_above = pflat + e * mask
                f_below = self._f(p_below)
                f_above = self._f(p_above)
                adfj = (f_above - f_below) / e[iparam]
                out.df.approx[:,
                              iparam] = adfj  # TODO(III): store data from multiple rpts?
                if do_hessian or do_ddf:
                    df_below = self._df(p_below)
                    df_above = self._df(p_above)
                    addfj = (df_above - df_below) / e[iparam]
                if do_ddf:
                    out.ddf.approx[:,
                                   iparam] = addfj[:,
                                                   iparam]  # TODO(III): store data from multiple rpts?
                if do_hessian:
                    out.H.approx[:,
                                 iparam].flat = addfj.flat  # TODO(III): store data from multiple rpts?
                converged = True  # TODO(III): could check for convergence here. currently, only one iteration is performed
                if converged: keepgoing[iparam] = False
            e[keepgoing] /= 2

        unflatten(self, pflat, include=self._free)
        self._reset()
        out.plabels = [
            'p' + x for x in flatten(self, include=self._free, labels=True)
        ]
        out.flabels = [
            'f' + x
            for x in flatten(self.eval(), include=self._free, labels=True)
        ]

        fields = ['df', 'ddf', 'H']
        for k in fields:
            v = out._getfield(k, None)
            if v == None: continue
            v.abserr = abs(v.exact - v.approx)
            v.maxabserr = v.abserr.max()
            v.propabserr = v.abserr / numpy.fmax(abs(v.approx), 1e-13)
            v.maxpropabserr = v.propabserr.max()

        if plot:
            import Plotting
            pylab = Plotting.load_pylab()

            fields = ['df', 'ddf', 'H']
            labels = {
                'df': (out.flabels, out.plabels, 'd%s / d%s'),
                'ddf': (out.flabels, out.plabels, 'd^2%s / d%s^2'),
                'H': (out.plabels, out.plabels, 'df/(d%s)(d%s)'),
            }
            got = dict([(k, k in out._fields) for k in fields])
            nplots = sum(got.values())
            for i, k in enumerate(fields):
                v = out._getfield(k, None)
                if v == None: continue
                if nplots > 1: pylab.subplot(1, nplots, i + 1)
                x = abs(v.approx.flatten())
                y = v.abserr.flatten()
                both0 = numpy.logical_and(x == 0.0, y == 0.0)
                x[both0] = numpy.nan
                y[both0] = numpy.nan
                x[x == 0.0] = 1e-13
                y[y == 0.0] = 1e-13
                x = numpy.log10(x)
                y = numpy.log10(y)
                pylab.cla()
                ax = pylab.gca()
                ax.indicator, = pylab.plot([numpy.nan, numpy.nan],
                                           [numpy.nan, numpy.nan],
                                           color=(1, 0, 1),
                                           linewidth=2)
                v.handles = pylab.plot(numpy.expand_dims(x, 0),
                                       numpy.expand_dims(y, 0),
                                       linestyle='None',
                                       marker='o',
                                       markersize=10,
                                       picker=5)
                lab = labels[k]
                for j, h in enumerate(v.handles):
                    subs = numpy.unravel_index(j, v.approx.shape)
                    h.txt = (lab[2] + '\nprop. abs. err. = %g') % (
                        lab[0][subs[0]], lab[1][subs[1]], v.propabserr.flat[j])
                ax.set_xlabel('log10 of abs approx value')
                ax.set_ylabel('log10 of abs error')
                ax.grid(True)

            def onpick(evt):
                h = evt.artist
                x, y = h.get_xdata(), h.get_ydata()
                ax = h.axes
                ax.set_title(h.txt)
                ind = ax.indicator
                xl, yl = numpy.asarray(ax.get_xlim()), numpy.asarray(
                    ax.get_ylim())
                ind.set_xdata([x.mean(), xl.mean()])
                ind.set_ydata([y.mean(), yl.max() + numpy.diff(yl) * 0.01])
                ind.set_clip_on(False)
                ind.set_color(h.get_color())
                pylab.draw()

            pylab.gcf().canvas.mpl_connect('pick_event', onpick)
            pylab.draw()

        return out