.. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:here  to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_functional_modeling_vectorial_functions_plot_quick_start_functions.py: Defining Python and symbolic functions: a quick start introduction to functions =============================================================================== Abstract -------- In this example, we show how to define Python and symbolic functions. Such functions can be evaluated by the library and used, for example, to propagate uncertainties. We focus on functions which have a vector input and a vector output. Introduction ------------ We consider the following example: * three input variables, * two outputs. Moreover, we assume that the input distribution has independent Gaussian marginals. The function is defined by the equations: .. math:: Y_1 = X_1 + X_2 + X_3 and .. math:: Y_2 = X_1 - X_2 X_3 for any :math:X_1,X_2,X_3 \in \mathbb{R}. The exact expectation and standard deviation of the output random variable are presented in the following table. ============= =========== ================== Variable Expectation Standard deviation ============= =========== ================== :math:Y_1 0 1.732 :math:Y_2 0 1.415 ============= =========== ================== .. code-block:: default import openturns as ot import openturns.viewer as viewer from matplotlib import pylab as plt ot.Log.Show(ot.Log.NONE) We first define the input random vector of the function. .. code-block:: default X0 = ot.Normal(0.,1.) X1 = ot.Normal(0.,1.) X2 = ot.Normal(0.,1.) inputDistribution = ot.ComposedDistribution((X0,X1,X2)) inputRandomVector = ot.RandomVector(inputDistribution) The Python function ------------------- Based on a Python function defined with the def keyword, the PythonFunction class creates a function. The simplest constructor of the PythonFunction class is: PythonFunction ( nbInputs , nbOutputs , myPythonFunc ) where * nbInputs: the number of inputs, * nbOutputs: the number of outputs, * myPythonFunc: a Python function. The goal of the PythonFunction class are: * to easily create a function in Python, * use all the power of the Python libraries in order to evaluate the function. The function mySimulator has the calling sequence y=mySimulator(x) where: * x: the input of the function, a vector with nbInputs dimensions, * y: the output of the function, a vector with nbOutputs dimensions. .. code-block:: default def mySimulator(x): y0=x+x+x y1=x-x*x y=[y0,y1] return y We now define the PythonFunction object. .. code-block:: default myfunction = ot.PythonFunction (3 ,2 , mySimulator ) This function can be evaluated using parentheses. It produces the same outputs as the mySimulator function. .. code-block:: default myfunction([1.,2.,3.]) .. raw:: html

[6,-5]

However, the newly created myfunction has services that the basic Python function did not have. For example, we can create a CompositeRandomVector on top of it, by associating it to the input random vector. .. code-block:: default outputVect = ot.CompositeRandomVector(myfunction, inputRandomVector) In the following example, we estimate the output mean based on a simple Monte-Carlo experiment using 10000 function evaluations. .. code-block:: default montecarlosize = 10000 outputSample = outputVect.getSample(montecarlosize) .. code-block:: default empiricalMean = outputSample.computeMean() print(empiricalMean) empiricalSd = outputSample.computeStandardDeviationPerComponent() print(empiricalSd) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none [-0.00526771,0.000853474] [1.735,1.38291] What types for x and for y ? ---------------------------- Not all types are possible for the inputs and outputs of the mySimulator function. The following table present some of the available types. All in all, any type which can be converted to or from a "vector" can be managed by the PythonFunction class. ==================== ======= ======== Type Input X Output Y ==================== ======= ======== list (Python) NO YES tuple (Python) NO YES array (NumPy) NO YES Point (OpenTURNS) YES YES ==================== ======= ======== The vectorized Python function ------------------------------ The PythonFunction class has a func_sample option which vectorizes the computation so that all the output values in the sample are computed from a single function call, without any for loop. To make this possible, the input and output is then a Sample instead of a Point. This often boosts performance (but not always). The calling sequence of a vectorized Python function is: def mySimulator (x): [...] return y myfunction = PythonFunction(nbInputs, nbOutputs, func_sample = mySimulator) where * x: the input of the function, a Sample with size nbExperiments (getSize) and dimension nbInputs (getDimension), * y: the output of the function * a numpy array with nbExperiments rows and nbOutputs columns * or a Sample with size nbExperiments and dimension nbOutputs In the following, we present an vectorization example based on the numpy module. .. code-block:: default import numpy as np .. code-block:: default def mySimulatorVect (x): # Convert NumericalSample > Array Numpy x = np.array (x) x0 = x[: ,0] # Extract column 0 x1 = x[: ,1] x2 = x[: ,2] y0 = x0 + x1 + x2 y1 = x0 - x1 * x2 # Stack the two rows y = np.vstack ((y0 ,y1 )) y = y.transpose () return y .. code-block:: default myfunctionVect = ot.PythonFunction (3, 2, func_sample = mySimulatorVect ) .. code-block:: default outputVect = ot.CompositeRandomVector(myfunctionVect, inputRandomVector) .. code-block:: default montecarlosize = 10000 outputSample = outputVect.getSample(montecarlosize) empiricalMean = outputSample.computeMean() print(empiricalMean) empiricalSd = outputSample.computeStandardDeviationPerComponent() print(empiricalSd) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none [-0.0246001,-0.0145294] [1.75224,1.41905] How to manage the history ------------------------- The MemoizeFunction class defines a history system to store the calls to the function. ==================== =============================================== Methods Description ==================== =============================================== enableHistory() enables the history (it is enabled by default) disableHistory() disables the history clearHistory() deletes the content of the history getHistoryInput() a Sample, the history of inputs X getHistoryOutput() a Sample, the history of outputs Y ==================== =============================================== .. code-block:: default myfunction = ot.PythonFunction (3 ,2 , mySimulator ) myfunction = ot.MemoizeFunction(myfunction) .. code-block:: default outputVariableOfInterest = ot.CompositeRandomVector(myfunction, inputRandomVector) montecarlosize = 10 outputSample = outputVariableOfInterest.getSample(montecarlosize) Get the history of input points. .. code-block:: default inputs = myfunction.getInputHistory() inputs .. raw:: html
v0 v1 v2 -0.9389956 0.1750352 -0.1627647 1.035602 1.085842 -1.491294 -2.299757 -1.231629 1.379118 -0.3600111 0.4002453 0.361149 -0.7034435 -0.3904179 -0.1066863 -1.194971 -1.615453 0.652794 -0.1920677 0.05895899 1.137312 -1.259093 -0.5378959 -0.8634301 -1.747308 -1.394032 0.6473908 -1.264755 -1.180456 -0.8008

Symbolic functions ------------------ The SymbolicFunction class can create symbolic functions whenever the function is simple enough to be expressed as a string. This has at least two significant advantages. * It generally improves the performance. * This allows to automatically evaluate the exact gradient and Hessian matrix. In practice, some functions cannot be expressed as a symbolic function: in this case, the Python function cannot be avoided. The calling sequence is the following:  myfunction = SymbolicFunction( list_of_inputs, list_of_formulas)  where * list_of_inputs: a list of nbInputs strings, the names of the input variables, * list_of_formulas: a list of nbOutputs strings, the equations. .. code-block:: default myfunction = ot.SymbolicFunction(("x0","x1","x2"),("x0 + x1 + x2","x0 - x1 * x2")) A SymbolicFunction, like any other function, can also have a history. .. code-block:: default myfunction = ot.MemoizeFunction(myfunction) .. code-block:: default outputVect = ot.CompositeRandomVector(myfunction, inputRandomVector) .. code-block:: default montecarlosize = 10000 outputSample = outputVect.getSample(montecarlosize) empiricalMean = outputSample.computeMean() print(empiricalMean) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none [0.0413268,0.0365706] Since the history is enabled, we can get the history of outputs of the function. .. code-block:: default outputs = myfunction.getOutputHistory() outputs[1:10,:] .. raw:: html
v0 v1 0.8445897 -1.740963 2.73993 1.804589 0.3751409 -0.121689 0.1117662 1.657584 -0.9433237 -1.293009 -5.914932 -5.656813 1.371743 0.4146196 -0.8976212 0.05640185 -2.626565 -1.659344

.. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 0.048 seconds) .. _sphx_glr_download_auto_functional_modeling_vectorial_functions_plot_quick_start_functions.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:Download Python source code: plot_quick_start_functions.py  .. container:: sphx-glr-download sphx-glr-download-jupyter :download:Download Jupyter notebook: plot_quick_start_functions.ipynb  .. only:: html .. rst-class:: sphx-glr-signature Gallery generated by Sphinx-Gallery _