%feature("docstring") OT::FunctionalChaosAlgorithm
"Functional chaos algorithm.

Available constructors:
    FunctionalChaosAlgorithm(*inputSample, outputSample*)

    FunctionalChaosAlgorithm(*inputSample, outputSample, distribution, adaptiveStrategy*)

    FunctionalChaosAlgorithm(*inputSample, outputSample, distribution, adaptiveStrategy, projectionStrategy*)

    FunctionalChaosAlgorithm(*model, distribution, adaptiveStrategy*)

    FunctionalChaosAlgorithm(*model, distribution, adaptiveStrategy, projectionStrategy*)

    FunctionalChaosAlgorithm(*inputSample, weights, outputSample, distribution, adaptiveStrategy*)

    FunctionalChaosAlgorithm(*inputSample, weights, outputSample, distribution, adaptiveStrategy, projectionStrategy*)

Parameters
----------
inputSample, outputSample : 2-d sequence of float
    Sample of the input - output random vectors
model : :class:`~openturns.Function`
    Model :math:`g` such as :math:`\vect{Y} = g(\vect{X})`.
distribution : :class:`~openturns.Distribution`
    Distribution of the random vector :math:`\vect{X}`
adaptiveStrategy : :class:`~openturns.AdaptiveStrategy`
    Strategy of selection of the different terms of the multivariate basis.
projectionStrategy : :class:`~openturns.ProjectionStrategy`
    Strategy of evaluation of the coefficients :math:`\alpha_k`
weights : sequence of float
    Weights :math:`\omega_i` associated to the data base

    Default values are :math:`\omega_i = \frac{1}{N}` where 
    *N=inputSample.getSize()*

See also
--------
FunctionalChaosResult

Notes
-----
Consider :math:`\vect{Y} = g(\vect{X})` with :math:`g: \Rset^d \rightarrow \Rset^p`, 
:math:`\vect{X} \sim \cL_{\vect{X}}` and :math:`\vect{Y}` with finite variance: 
:math:`g\in L_{\cL_{\vect{X}}}^2(\Rset^d, \Rset^p)`.

When  :math:`p>1`, the functional chaos algorithm is used on each marginal 
of :math:`\vect{Y}`, using the same multivariate orthonormal basis for all the marginals. 
Thus, the algorithm is detailed here for a scalar output :math:`Y` and 
:math:`g: \Rset^d \rightarrow \Rset`.

Let :math:`T: \Rset^d \rightarrow \Rset^d` be an isoprobabilistic transformation
such that :math:`\vect{Z} = T(\vect{X}) \sim \mu`. We note :math:`f = g \circ T^{-1}`, then :math:`f \in L_{\mu}^2(\Rset^d, \Rset)`.

Let :math:`(\Psi_k)_{k \in \Nset}` be an orthonormal multivariate basis of 
:math:`L^2_{\mu}(\Rset^d,\Rset)`.

Then the functional chaos decomposition of *f* writes:

.. math::

    f = g\circ T^{-1} = \sum_{k=0}^{\infty} \vect{\alpha}_k \Psi_k 


which can be truncated to the finite set :math:`K \in \Nset`:

.. math::

    \tilde{f} =  \sum_{k \in K} \vect{\alpha}_k \Psi_k 


The approximation :math:`\tilde{f}` can be used to build an efficient random 
generator of :math:`Y` based on the random vector :math:`\vect{Z}`. 
It writes:

.. math::

    \tilde{Y} = \tilde{f}(\vect{Z})

For more details, see :class:`~openturns.FunctionalChaosRandomVector`.

The functional chaos decomposition can be used to build a meta model of *g*, 
which writes:

.. math::

    \tilde{g} = \tilde{f} \circ T

If the basis :math:`(\Psi_k)_{k \in \Nset}` has been obtained by tensorisation of
univariate orthonormal basis, then the distribution :math:`\mu` writes  
:math:`\mu = \prod_{i=1}^d \mu_i`. In that case only, the Sobol indices can
easily be deduced from the coefficients :math:`\alpha_k`.

We detail here all the steps required in order to create a functional chaos 
algorithm.

**Step 1 - Construction of the multivariate orthonormal basis**: the
multivariate orthonornal basis :math:`(\Psi_k(\vect{x}))_{k \in \Nset}` is built
as the tensor product of orthonormal univariate families.

The univariate bases may be:

    - *polynomials*: the associated distribution :math:`\mu_i` is continuous or discrete. 
      Note that it is possible to build the polynomial family orthonormal to any univariate 
      distribution :math:`\mu_i` under some conditions. 
      For more details, see :class:`~openturns.StandardDistributionPolynomialFactory`;

    - Haar wavelets: they enable to approximate functions with discontinuities.
      For more details, see :class:`~openturns.HaarWaveletFactory`,;

    - Fourier series: for more details, see :class:`~openturns.FourierSeriesFactory`.

Furthermore, the numerotation of the multivariate orthonormal basis :math:`(\Psi_k(\vect{z}))_k` 
is given by an enumerate function which defines a regular way to generate the collection of degres 
used for the univariate polynomials : an enumerate function represents a bijection 
:math:`\Nset \rightarrow \Nset^d`. See :class:`~openturns.LinearEnumerateFunction` or :class:`~openturns.HyperbolicAnisotropicEnumerateFunction` 
for more details.

**Step 2 - Truncation strategy of the multivariate orthonormal basis**: a
strategy must be chosen for the selection of the different terms of the
multivariate basis. The selected terms are gathered in the subset *K*.

For more details on the possible strategies, see :class:`~openturns.FixedStrategy`,
:class:`~openturns.SequentialStrategy` and :class:`~openturns.CleaningStrategy`.

**Step 3 -  Evaluation strategy of the coefficients**: a
strategy must be chosen for the estimation of te coefficients :math:`\alpha_k`. 
The vector :math:`\vect{\alpha} = (\alpha_k)_{k \in K}` is equivalently defined by:

.. math::
    :label: quadEr

    \vect{\alpha} = \argmin_{\vect{\alpha} \in \Rset^K}\Expect{\left( g \circ T^{-1}(\vect{Z}) - \sum_{k \in K} \alpha_k \Psi_k (\vect{Z})\right)^2}

or

.. math::
    :label: scalProd

    \alpha_k =  <g \circ T^{-1}(\vect{Z}), \Psi_k (\vect{Z})>_{\mu} = \Expect{  g \circ T^{-1}(\vect{Z}) \Psi_k (\vect{Z}) }

where the mean :math:`\Expect{.}` is evaluated with respect to the measure :math:`\mu`.

Relation :eq:`quadEr` means that the coefficients :math:`(\alpha_k)_{k \in K}`
minimize the quadratic error between the model and the polynomial approximation.
For more details, see :class:`~openturns.LeastSquaresStrategy`.

Relation  :eq:`scalProd` means that :math:`\alpha_k` is the scalar product of the
model with the *k-th* element of the orthonormal basis :math:`(\Psi_k)_{k \in \Nset}`.
For more details, see :class:`~openturns.IntegrationStrategy`.

Examples
--------
Create the model:

>>> import openturns as ot
>>> ot.RandomGenerator.SetSeed(0)
>>> inputDim = 1
>>> model = ot.SymbolicFunction(['x'], ['x*sin(x)'])
>>> distribution = ot.ComposedDistribution([ot.Uniform()]*inputDim)

Build the multivariate orthonormal basis:

>>> polyColl = [0.0]*inputDim
>>> for i in range(distribution.getDimension()):
...     polyColl[i] = ot.StandardDistributionPolynomialFactory(distribution.getMarginal(i))
>>> enumerateFunction = ot.LinearEnumerateFunction(inputDim)
>>> productBasis = ot.OrthogonalProductPolynomialFactory(polyColl, enumerateFunction)

Define the  strategy to truncate the multivariate orthonormal basis:
We choose all the polynomials of degree <= 4

>>> degree = 4
>>> indexMax = enumerateFunction.getStrataCumulatedCardinal(degree)
>>> print(indexMax)
5

We keep all the polynomials of degree <= 4 (which corresponds to the 5 first ones):

>>> adaptiveStrategy = ot.FixedStrategy(productBasis, indexMax)

Define the evaluation strategy of the  coefficients:

>>> samplingSize = 50
>>> experiment = ot.MonteCarloExperiment(samplingSize)
>>> projectionStrategy = ot.LeastSquaresStrategy(experiment)

Create the Functional Chaos Algorithm:

>>> algo = ot.FunctionalChaosAlgorithm(model, distribution, adaptiveStrategy,
...                                    projectionStrategy)
>>> algo.run()

Get the result:

>>> functionalChaosResult = algo.getResult()
>>> metamodel = functionalChaosResult.getMetaModel()

Test it:

>>> X = [0.5]
>>> print(model(X))
[0.239713]
>>> print(metamodel(X))
[0.239514]
"

// ---------------------------------------------------------------------

%feature("docstring") OT::FunctionalChaosAlgorithm::getMaximumResidual
"Get the maximum residual.

Returns
-------
residual : float
    Residual value needed in the projection strategy. 

    Default value is :math:`0`."

// ---------------------------------------------------------------------

%feature("docstring") OT::FunctionalChaosAlgorithm::getProjectionStrategy
"Get the projection strategy.

Returns
-------
strategy : :class:`~openturns.ProjectionStrategy`
    Projection strategy.

Notes
-----
The projection strategy selects the different terms of the
multivariate basis to define the subset *K*."

// ---------------------------------------------------------------------

%feature("docstring") OT::FunctionalChaosAlgorithm::getAdaptiveStrategy
"Get the adaptive strategy.

Returns
-------
adaptiveStrategy : :class:`~openturns.AdaptiveStrategy`
    Strategy of selection of the different terms of the multivariate basis."

// ---------------------------------------------------------------------

%feature("docstring") OT::FunctionalChaosAlgorithm::getResult
"Get the results of the metamodel computation.

Returns
-------
result : :class:`~openturns.FunctionalChaosResult`
    Result structure, created by the method :py:meth:`run`."

// ---------------------------------------------------------------------

%feature("docstring") OT::FunctionalChaosAlgorithm::run
"Compute the metamodel.

Notes
-----
Evaluates the metamodel and stores all the results in a result structure."

// ---------------------------------------------------------------------

%feature("docstring") OT::FunctionalChaosAlgorithm::setMaximumResidual
"Set the maximum residual.

Parameters
----------
residual : float
    Residual value needed in the projection strategy. 

    Default value is :math:`0`."

// ---------------------------------------------------------------------

%feature("docstring") OT::FunctionalChaosAlgorithm::setProjectionStrategy
"Set the projection strategy.

Parameters
----------
strategy : :class:`~openturns.ProjectionStrategy`
    Strategy to estimate the coefficients :math:`\alpha_k`."
