<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 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)
Step1:  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.
Step2:  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.
Step3:  Now we do a similar thing with the effective quadrature toolbox to make a quadratic polynomial surrogate.
<ASSISTANT_TASK:>
Python Code:
from horsetailmatching import HorsetailMatching, UniformParameter
from horsetailmatching.demoproblems import TP2
from horsetailmatching.surrogates import PolySurrogate
import numpy as np
uparams = [UniformParameter(), UniformParameter()]
Explanation: 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.
End of explanation
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]))
Explanation: 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.
End of explanation
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]))
Explanation: 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.
End of explanation
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]))
Explanation: Now we do a similar thing with the effective quadrature toolbox to make a quadratic polynomial surrogate.
End of explanation
<END_TASK>