When we cannot afford to sample the quantity of interest many times at every design within an optimization, we can use surrogate models instead. Here we will show you how to use third party surrogates as well as the polynomial chaos surrogate provided with horsetail matching.

For the third party surrogates, we will use the effective-quadratures package [Seshadri, P. and Parks, G. (2017) Effective-Quadratures (EQ): Polynomials for Computational Engineering Studies, The Open Journal, http://dx.doi.org/10.21105/joss.0016], (also see http://www.effective-quadratures.org/). We will also use pyKriging [pyKriging 0.5281/zenodo.593877] (also see http://pykriging.com/).

The HorstailMaching object can take a "surrogate" argument, which should be a function that takes an np.ndarray of values of the uncertain parameters of size (num_points, num_uncertainties), and a np.ndarray of the quantity of interest evaluated at these values of size (num_points) that returns a function that predicts the function output at any value of the uncertainties. num_points is the number of points at which the surrogate is to be evaluated, and num_uncertainties is the number of uncertain parameters. The object also takes a "surrogate_points" argument, which is a list of points (values of u) at which horsetail matching calls the qoi function in order to fit the surrogate.

The following examples should make this more clear.


In [1]:
from horsetailmatching import HorsetailMatching, UniformParameter
from horsetailmatching.demoproblems import TP2
from horsetailmatching.surrogates import PolySurrogate

import numpy as np

uparams = [UniformParameter(), UniformParameter()]

Lets start with the built in in polynomial chaos surrogate. This finds the coefficients of a polynomial expansion by evaluating the inner product of the qoi function with each polynomial using gaussian quadrature.

The polynomial chaos expansion used by the PolySurrogate class uses specific quadrature points over the uncertainty space to perform efficient integration, and so we must tell the HorsetailMatching object that these are the points at which to evaluate the quantity of interest when making the surrogate. This is done with the surrogate_points argument.


In [2]:
thePoly = PolySurrogate(dimensions=len(uparams), order=4)
u_quadrature = thePoly.getQuadraturePoints()

def myPolynomialChaosSurrogate(u_quad, q_quad):
    thePoly.train(q_quad)
    return thePoly.predict

theHM = HorsetailMatching(TP2, uparams, surrogate=myPolynomialChaosSurrogate, surrogate_points=u_quadrature)
print('Metric evaluated with polynomial chaos surrogate: ', theHM.evalMetric([0, 1]))
theHM.surrogate = None
print('Metric evaluated with direct sampling: ', theHM.evalMetric([0, 1]))


('Metric evaluated with polynomial chaos surrogate: ', 13.997065650410487)
('Metric evaluated with direct sampling: ', 13.997065650410491)

Next we use the pyKriging samplingplan function to give us 20 points found via latin hypercube sampling at which to evaluate the metric to create the surrogate. Then we create a function in the form required by horsetail matching called myKrigingSurrogate, and pass this as the surrogate argument when making the horestail matching object, along with the LHS points as the surrogate_points argument. Here we modify the already created horsetail matching object instead of making a new one.


In [3]:
from pyKriging.krige import kriging
from pyKriging.samplingplan import samplingplan

sp = samplingplan(2)
u_sampling = sp.optimallhc(25)

def myKrigingSurrogate(u_lhc, q_lhc):
    krig = kriging(u_lhc, q_lhc)
    krig.train()
    return krig.predict

theHM.surrogate = myKrigingSurrogate
theHM.surrogate_points = u_sampling
print('Metric evaluated with kriging surrogate: ', theHM.evalMetric([0, 1]))
theHM.surrogate = None
print('Metric evaluated with direct sampling: ', theHM.evalMetric([0, 1]))


('Metric evaluated with kriging surrogate: ', 14.00474151445389)
('Metric evaluated with direct sampling: ', 13.997065650410491)

Now we do a similar thing with the effective quadrature toolbox to make a quadratic polynomial surrogate.


In [4]:
from equadratures import Polyreg

U1, U2 = np.meshgrid(np.linspace(-1, 1, 5), np.linspace(-1, 1, 5))
u_tensor = np.vstack([U1.flatten(), U2.flatten()]).T

def myQuadraticSurrogate(u_tensor, q_tensor):
    poly = Polyreg(np.mat(u_tensor), np.mat(q_tensor).T, 'quadratic')
    def model(u):
        return poly.testPolynomial(np.mat(u))
    return model

theHM.surrogate = myQuadraticSurrogate
theHM.surrogate_points = u_tensor
print('Metric evaluated with quadratic surrogate: ', theHM.evalMetric([0, 1]))
theHM.surrogate = None
print('Metric evaluated with direct sampling: ', theHM.evalMetric([0, 1]))


('Metric evaluated with quadratic surrogate: ', 14.239792573235533)
('Metric evaluated with direct sampling: ', 13.997065650410491)

Surrogates can also be used with gradients, for details see the next tutorial, which gives a full example of using all of the functionality available in the horsetail matching package: http://nbviewer.jupyter.org/github/lwcook/horsetail-matching/blob/master/notebooks/FullExample.ipynb

For other tutorials, please visit http://www-edc.eng.cam.ac.uk/aerotools/horsetailmatching/


In [ ]: