From 96e5e7f167f1dbca71a69e597bed28c78d847d50 Mon Sep 17 00:00:00 2001 From: Jean-Philippe ARGAUD Date: Wed, 29 Mar 2023 13:46:41 +0200 Subject: [PATCH] Documentation and code update OSCT --- doc/en/snippets/ModuleCompatibility.rst | 2 +- doc/fr/snippets/ModuleCompatibility.rst | 2 +- .../ObservationSimulationComparisonTest.py | 353 ++++++++++++++++++ .../daYacsSchemaCreator/infos_daComposant.py | 6 + 4 files changed, 361 insertions(+), 2 deletions(-) create mode 100644 src/daComposant/daAlgorithms/ObservationSimulationComparisonTest.py diff --git a/doc/en/snippets/ModuleCompatibility.rst b/doc/en/snippets/ModuleCompatibility.rst index 3d239ba..932af34 100644 --- a/doc/en/snippets/ModuleCompatibility.rst +++ b/doc/en/snippets/ModuleCompatibility.rst @@ -12,7 +12,7 @@ guarantee). :header: "Tool", "Minimal version", "Reached version" :widths: 20, 10, 10 - Python, 3.6.5, 3.10.9 + Python, 3.6.5, 3.10.10 Numpy, 1.14.3, 1.24.2 Scipy, 0.19.1, 1.10.1 MatplotLib, 2.2.2, 3.7.1 diff --git a/doc/fr/snippets/ModuleCompatibility.rst b/doc/fr/snippets/ModuleCompatibility.rst index 74964c4..32e5d6c 100644 --- a/doc/fr/snippets/ModuleCompatibility.rst +++ b/doc/fr/snippets/ModuleCompatibility.rst @@ -12,7 +12,7 @@ la version atteinte (mais cela reste sans garantie). :header: "Outil", "Version minimale", "Version atteinte" :widths: 20, 10, 10 - Python, 3.6.5, 3.10.9 + Python, 3.6.5, 3.10.10 Numpy, 1.14.3, 1.24.2 Scipy, 0.19.1, 1.10.1 MatplotLib, 2.2.2, 3.7.1 diff --git a/src/daComposant/daAlgorithms/ObservationSimulationComparisonTest.py b/src/daComposant/daAlgorithms/ObservationSimulationComparisonTest.py new file mode 100644 index 0000000..85184b3 --- /dev/null +++ b/src/daComposant/daAlgorithms/ObservationSimulationComparisonTest.py @@ -0,0 +1,353 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2008-2023 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D + +import numpy, copy, logging +from daCore import BasicObjects, PlatformInfo +mpr = PlatformInfo.PlatformInfo().MachinePrecision() +mfp = PlatformInfo.PlatformInfo().MaximumPrecision() + +# ============================================================================== +class ElementaryAlgorithm(BasicObjects.Algorithm): + def __init__(self): + BasicObjects.Algorithm.__init__(self, "OBSERVATIONSIMULATIONCOMPARISONTEST") + self.defineRequiredParameter( + name = "ShowElementarySummary", + default = True, + typecast = bool, + message = "Calcule et affiche un résumé à chaque évaluation élémentaire", + ) + self.defineRequiredParameter( + name = "NumberOfPrintedDigits", + default = 5, + typecast = int, + message = "Nombre de chiffres affichés pour les impressions de réels", + minval = 0, + ) + self.defineRequiredParameter( + name = "NumberOfRepetition", + default = 1, + typecast = int, + message = "Nombre de fois où l'exécution de la fonction est répétée", + minval = 1, + ) + self.defineRequiredParameter( + name = "ResultTitle", + default = "", + typecast = str, + message = "Titre du tableau et de la figure", + ) + self.defineRequiredParameter( + name = "SetDebug", + default = False, + typecast = bool, + message = "Activation du mode debug lors de l'exécution", + ) + self.defineRequiredParameter( + name = "StoreSupplementaryCalculations", + default = [], + typecast = tuple, + message = "Liste de calculs supplémentaires à stocker et/ou effectuer", + listval = [ + "CostFunctionJ", + "CostFunctionJb", + "CostFunctionJo", + "CurrentState", + "Innovation", + "InnovationAtCurrentState", + "SimulatedObservationAtCurrentState", + ] + ) + self.requireInputArguments( + mandatory= ("Xb", "Y", "HO", "R", "B"), + ) + self.setAttributes(tags=( + "Checking", + )) + + def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None): + self._pre_run(Parameters, Xb, Y, U, HO, EM, CM, R, B, Q) + # + Hm = HO["Direct"].appliedTo + # + X0 = copy.copy( Xb ) + Y0 = copy.copy( Y ) + # + # ---------- + if len(self._parameters["StoreSupplementaryCalculations"]) > 0: + BI = B.getI() + RI = R.getI() + def CostFunction(x,HmX): + _X = numpy.ravel( x ) + _HX = numpy.ravel( HmX ) + _X0 = numpy.ravel( X0 ) + _Y0 = numpy.ravel( Y0 ) + Jb = float( 0.5 * (_X - _X0).T * (BI * (_X - _X0)) ) + Jo = float( 0.5 * (_Y0 - _HX).T * (RI * (_Y0 - _HX)) ) + J = Jb + Jo + self.StoredVariables["CostFunctionJb"].store( Jb ) + self.StoredVariables["CostFunctionJo"].store( Jo ) + self.StoredVariables["CostFunctionJ" ].store( J ) + return J, Jb, Jo + # ---------- + __s = self._parameters["ShowElementarySummary"] + __p = self._parameters["NumberOfPrintedDigits"] + __r = self._parameters["NumberOfRepetition"] + # + __marge = 5*u" " + __flech = 3*"="+"> " + msgs = ("\n") # 1 + if len(self._parameters["ResultTitle"]) > 0: + __rt = str(self._parameters["ResultTitle"]) + msgs += (__marge + "====" + "="*len(__rt) + "====\n") + msgs += (__marge + " " + __rt + "\n") + msgs += (__marge + "====" + "="*len(__rt) + "====\n") + else: + msgs += (__marge + "%s\n"%self._name) + msgs += (__marge + "%s\n"%("="*len(self._name),)) + # + msgs += ("\n") + msgs += (__marge + "This test allows to analyze the (repetition of the) launch of some\n") + msgs += (__marge + "given simulation operator F, applied to one single vector argument x,\n") + msgs += (__marge + "and its (repeated) comparison to observations or measures y.\n") + msgs += (__marge + "The output shows simple statistics related to its successful execution,\n") + msgs += (__marge + "or related to the similarities of repetition of its execution.\n") + msgs += ("\n") + msgs += (__flech + "Information before launching:\n") + msgs += (__marge + "-----------------------------\n") + msgs += ("\n") + msgs += (__marge + "Characteristics of input vector X, internally converted:\n") + msgs += (__marge + " Type...............: %s\n")%type( X0 ) + msgs += (__marge + " Length of vector...: %i\n")%max(numpy.ravel( X0 ).shape) + msgs += (__marge + " Minimum value......: %."+str(__p)+"e\n")%numpy.min( X0 ) + msgs += (__marge + " Maximum value......: %."+str(__p)+"e\n")%numpy.max( X0 ) + msgs += (__marge + " Mean of vector.....: %."+str(__p)+"e\n")%numpy.mean( X0, dtype=mfp ) + msgs += (__marge + " Standard error.....: %."+str(__p)+"e\n")%numpy.std( X0, dtype=mfp ) + msgs += (__marge + " L2 norm of vector..: %."+str(__p)+"e\n")%numpy.linalg.norm( X0 ) + msgs += ("\n") + msgs += (__marge + "Characteristics of input vector of observations Yobs, internally converted:\n") + msgs += (__marge + " Type...............: %s\n")%type( Y0 ) + msgs += (__marge + " Length of vector...: %i\n")%max(numpy.ravel( Y0 ).shape) + msgs += (__marge + " Minimum value......: %."+str(__p)+"e\n")%numpy.min( Y0 ) + msgs += (__marge + " Maximum value......: %."+str(__p)+"e\n")%numpy.max( Y0 ) + msgs += (__marge + " Mean of vector.....: %."+str(__p)+"e\n")%numpy.mean( Y0, dtype=mfp ) + msgs += (__marge + " Standard error.....: %."+str(__p)+"e\n")%numpy.std( Y0, dtype=mfp ) + msgs += (__marge + " L2 norm of vector..: %."+str(__p)+"e\n")%numpy.linalg.norm( Y0 ) + msgs += ("\n") + msgs += (__marge + "%s\n\n"%("-"*75,)) + # + if self._parameters["SetDebug"]: + CUR_LEVEL = logging.getLogger().getEffectiveLevel() + logging.getLogger().setLevel(logging.DEBUG) + if __r > 1: + msgs += (__flech + "Beginning of repeated evaluation, activating debug\n") + else: + msgs += (__flech + "Beginning of evaluation, activating debug\n") + else: + if __r > 1: + msgs += (__flech + "Beginning of repeated evaluation, without activating debug\n") + else: + msgs += (__flech + "Beginning of evaluation, without activating debug\n") + print(msgs) # 1 + # + # ---------- + HO["Direct"].disableAvoidingRedundancy() + # ---------- + Ys = [] + Ds = [] + Js = [] + _Y0 = numpy.ravel( Y0 ) + for i in range(__r): + if self._toStore("CurrentState"): + self.StoredVariables["CurrentState"].store( X0 ) + if __s: + msgs = (__marge + "%s\n"%("-"*75,)) # 2-1 + if __r > 1: + msgs += ("\n") + msgs += (__flech + "Repetition step number %i on a total of %i\n"%(i+1,__r)) + msgs += ("\n") + msgs += (__flech + "Launching operator sequential evaluation\n") + print(msgs) # 2-1 + # + Yn = Hm( X0 ) + # + if _Y0.size != Yn.size: + raise ValueError("The size %i of observations Y and %i of observed calculation F(X) are different, they have to be identical."%(Y0.size,Yn.size)) + # + Dn = _Y0 - numpy.ravel( Yn ) + # + if __s: + msgs = ("\n") # 2-2 + msgs += (__flech + "End of operator sequential evaluation\n") + msgs += ("\n") + msgs += (__flech + "Information after evaluation:\n") + msgs += ("\n") + msgs += (__marge + "Characteristics of simulated output vector Y=F(X), to compare to others:\n") + msgs += (__marge + " Type...............: %s\n")%type( Yn ) + msgs += (__marge + " Length of vector...: %i\n")%max(numpy.ravel( Yn ).shape) + msgs += (__marge + " Minimum value......: %."+str(__p)+"e\n")%numpy.min( Yn ) + msgs += (__marge + " Maximum value......: %."+str(__p)+"e\n")%numpy.max( Yn ) + msgs += (__marge + " Mean of vector.....: %."+str(__p)+"e\n")%numpy.mean( Yn, dtype=mfp ) + msgs += (__marge + " Standard error.....: %."+str(__p)+"e\n")%numpy.std( Yn, dtype=mfp ) + msgs += (__marge + " L2 norm of vector..: %."+str(__p)+"e\n")%numpy.linalg.norm( Yn ) + msgs += ("\n") + msgs += (__marge + "Characteristics of increment between observations Yobs and simulated output vector Y=F(X):\n") + msgs += (__marge + " Type...............: %s\n")%type( Dn ) + msgs += (__marge + " Length of vector...: %i\n")%max(numpy.ravel( Dn ).shape) + msgs += (__marge + " Minimum value......: %."+str(__p)+"e\n")%numpy.min( Dn ) + msgs += (__marge + " Maximum value......: %."+str(__p)+"e\n")%numpy.max( Dn ) + msgs += (__marge + " Mean of vector.....: %."+str(__p)+"e\n")%numpy.mean( Dn, dtype=mfp ) + msgs += (__marge + " Standard error.....: %."+str(__p)+"e\n")%numpy.std( Dn, dtype=mfp ) + msgs += (__marge + " L2 norm of vector..: %."+str(__p)+"e\n")%numpy.linalg.norm( Dn ) + if len(self._parameters["StoreSupplementaryCalculations"]) > 0: + J, Jb, Jo = CostFunction( X0, Yn ) + if self._toStore("CostFunctionJ"): + Js.append( J ) + msgs += ("\n") + msgs += (__marge + " Cost function J....: %."+str(__p)+"e\n")%J + msgs += (__marge + " Cost function Jb=0.: %."+str(__p)+"e\n")%Jb + msgs += (__marge + " Cost function Jo...: %."+str(__p)+"e\n")%Jo + print(msgs) # 2-2 + if self._toStore("SimulatedObservationAtCurrentState"): + self.StoredVariables["SimulatedObservationAtCurrentState"].store( numpy.ravel(Yn) ) + if self._toStore("Innovation"): + self.StoredVariables["Innovation"].store( Dn ) + if self._toStore("InnovationAtCurrentState"): + self.StoredVariables["InnovationAtCurrentState"].store( Dn ) + # + Ys.append( copy.copy( numpy.ravel( + Yn + ) ) ) + Ds.append( copy.copy( numpy.ravel( + Dn + ) ) ) + # ---------- + HO["Direct"].enableAvoidingRedundancy() + # ---------- + # + msgs = (__marge + "%s\n\n"%("-"*75,)) # 3 + if self._parameters["SetDebug"]: + if __r > 1: + msgs += (__flech + "End of repeated evaluation, deactivating debug if necessary\n") + else: + msgs += (__flech + "End of evaluation, deactivating debug if necessary\n") + logging.getLogger().setLevel(CUR_LEVEL) + else: + if __r > 1: + msgs += (__flech + "End of repeated evaluation, without deactivating debug\n") + else: + msgs += (__flech + "End of evaluation, without deactivating debug\n") + msgs += ("\n") + msgs += (__marge + "%s\n"%("-"*75,)) + # + if __r > 1: + msgs += ("\n") + msgs += (__flech + "Launching statistical summary calculation for %i states\n"%__r) + msgs += ("\n") + msgs += (__marge + "%s\n"%("-"*75,)) + msgs += ("\n") + msgs += (__flech + "Statistical analysis of the outputs obtained through sequential repeated evaluations\n") + msgs += ("\n") + msgs += (__marge + "(Remark: numbers that are (about) under %.0e represent 0 to machine precision)\n"%mpr) + msgs += ("\n") + Yy = numpy.array( Ys ) + msgs += (__marge + "Number of evaluations...........................: %i\n")%len( Ys ) + msgs += ("\n") + msgs += (__marge + "Characteristics of the whole set of outputs Y:\n") + msgs += (__marge + " Size of each of the outputs...................: %i\n")%Ys[0].size + msgs += (__marge + " Minimum value of the whole set of outputs.....: %."+str(__p)+"e\n")%numpy.min( Yy ) + msgs += (__marge + " Maximum value of the whole set of outputs.....: %."+str(__p)+"e\n")%numpy.max( Yy ) + msgs += (__marge + " Mean of vector of the whole set of outputs....: %."+str(__p)+"e\n")%numpy.mean( Yy, dtype=mfp ) + msgs += (__marge + " Standard error of the whole set of outputs....: %."+str(__p)+"e\n")%numpy.std( Yy, dtype=mfp ) + msgs += ("\n") + Ym = numpy.mean( numpy.array( Ys ), axis=0, dtype=mfp ) + msgs += (__marge + "Characteristics of the vector Ym, mean of the outputs Y:\n") + msgs += (__marge + " Size of the mean of the outputs...............: %i\n")%Ym.size + msgs += (__marge + " Minimum value of the mean of the outputs......: %."+str(__p)+"e\n")%numpy.min( Ym ) + msgs += (__marge + " Maximum value of the mean of the outputs......: %."+str(__p)+"e\n")%numpy.max( Ym ) + msgs += (__marge + " Mean of the mean of the outputs...............: %."+str(__p)+"e\n")%numpy.mean( Ym, dtype=mfp ) + msgs += (__marge + " Standard error of the mean of the outputs.....: %."+str(__p)+"e\n")%numpy.std( Ym, dtype=mfp ) + msgs += ("\n") + Ye = numpy.mean( numpy.array( Ys ) - Ym, axis=0, dtype=mfp ) + msgs += (__marge + "Characteristics of the mean of the differences between the outputs Y and their mean Ym:\n") + msgs += (__marge + " Size of the mean of the differences...........: %i\n")%Ye.size + msgs += (__marge + " Minimum value of the mean of the differences..: %."+str(__p)+"e\n")%numpy.min( Ye ) + msgs += (__marge + " Maximum value of the mean of the differences..: %."+str(__p)+"e\n")%numpy.max( Ye ) + msgs += (__marge + " Mean of the mean of the differences...........: %."+str(__p)+"e\n")%numpy.mean( Ye, dtype=mfp ) + msgs += (__marge + " Standard error of the mean of the differences.: %."+str(__p)+"e\n")%numpy.std( Ye, dtype=mfp ) + msgs += ("\n") + msgs += (__marge + "%s\n"%("-"*75,)) + msgs += ("\n") + msgs += (__flech + "Statistical analysis of the increments obtained through sequential repeated evaluations\n") + msgs += ("\n") + msgs += (__marge + "(Remark: numbers that are (about) under %.0e represent 0 to machine precision)\n"%mpr) + msgs += ("\n") + Dy = numpy.array( Ds ) + msgs += (__marge + "Number of evaluations...........................: %i\n")%len( Ds ) + msgs += ("\n") + msgs += (__marge + "Characteristics of the whole set of increments D:\n") + msgs += (__marge + " Size of each of the outputs...................: %i\n")%Ds[0].size + msgs += (__marge + " Minimum value of the whole set of increments..: %."+str(__p)+"e\n")%numpy.min( Dy ) + msgs += (__marge + " Maximum value of the whole set of increments..: %."+str(__p)+"e\n")%numpy.max( Dy ) + msgs += (__marge + " Mean of vector of the whole set of increments.: %."+str(__p)+"e\n")%numpy.mean( Dy, dtype=mfp ) + msgs += (__marge + " Standard error of the whole set of increments.: %."+str(__p)+"e\n")%numpy.std( Dy, dtype=mfp ) + msgs += ("\n") + Dm = numpy.mean( numpy.array( Ds ), axis=0, dtype=mfp ) + msgs += (__marge + "Characteristics of the vector Dm, mean of the increments D:\n") + msgs += (__marge + " Size of the mean of the increments............: %i\n")%Dm.size + msgs += (__marge + " Minimum value of the mean of the increments...: %."+str(__p)+"e\n")%numpy.min( Dm ) + msgs += (__marge + " Maximum value of the mean of the increments...: %."+str(__p)+"e\n")%numpy.max( Dm ) + msgs += (__marge + " Mean of the mean of the increments............: %."+str(__p)+"e\n")%numpy.mean( Dm, dtype=mfp ) + msgs += (__marge + " Standard error of the mean of the increments..: %."+str(__p)+"e\n")%numpy.std( Dm, dtype=mfp ) + msgs += ("\n") + De = numpy.mean( numpy.array( Ds ) - Dm, axis=0, dtype=mfp ) + msgs += (__marge + "Characteristics of the mean of the differences between the increments D and their mean Dm:\n") + msgs += (__marge + " Size of the mean of the differences...........: %i\n")%De.size + msgs += (__marge + " Minimum value of the mean of the differences..: %."+str(__p)+"e\n")%numpy.min( De ) + msgs += (__marge + " Maximum value of the mean of the differences..: %."+str(__p)+"e\n")%numpy.max( De ) + msgs += (__marge + " Mean of the mean of the differences...........: %."+str(__p)+"e\n")%numpy.mean( De, dtype=mfp ) + msgs += (__marge + " Standard error of the mean of the differences.: %."+str(__p)+"e\n")%numpy.std( De, dtype=mfp ) + # + if self._toStore("CostFunctionJ"): + msgs += ("\n") + Jj = numpy.array( Js ) + msgs += (__marge + "%s\n\n"%("-"*75,)) + msgs += (__marge + "Number of evaluations...........................: %i\n")%len( Js ) + msgs += ("\n") + msgs += (__marge + "Characteristics of the whole set of cost function J values:\n") + msgs += (__marge + " Minimum value of the whole set of J...........: %."+str(__p)+"e\n")%numpy.min( Jj ) + msgs += (__marge + " Maximum value of the whole set of J...........: %."+str(__p)+"e\n")%numpy.max( Jj ) + msgs += (__marge + " Mean of vector of the whole set of J..........: %."+str(__p)+"e\n")%numpy.mean( Jj, dtype=mfp ) + msgs += (__marge + " Standard error of the whole set of J..........: %."+str(__p)+"e\n")%numpy.std( Jj, dtype=mfp ) + msgs += ("\n") + msgs += (__marge + "%s\n"%("-"*75,)) + # + msgs += ("\n") + msgs += (__marge + "End of the \"%s\" verification\n\n"%self._name) + msgs += (__marge + "%s\n"%("-"*75,)) + print(msgs) # 3 + # + self._post_run(HO) + return 0 + +# ============================================================================== +if __name__ == "__main__": + print('\n AUTODIAGNOSTIC\n') diff --git a/src/daSalome/daYacsSchemaCreator/infos_daComposant.py b/src/daSalome/daYacsSchemaCreator/infos_daComposant.py index 8edd3b3..5269e44 100644 --- a/src/daSalome/daYacsSchemaCreator/infos_daComposant.py +++ b/src/daSalome/daYacsSchemaCreator/infos_daComposant.py @@ -106,6 +106,7 @@ CheckAlgos = [ "AdjointTest", "TangentTest", "LocalSensitivityTest", + "ObservationSimulationComparisonTest", "SamplingTest", "ParallelFunctionTest", "ControledFunctionTest", @@ -220,6 +221,11 @@ AlgoDataRequirements["LocalSensitivityTest"] = [ "Observation", "ObservationOperator", ] +AlgoDataRequirements["ObservationSimulationComparisonTest"] = [ + "CheckingPoint", + "Observation", + "ObservationOperator", + ] AlgoDataRequirements["SamplingTest"] = [ "CheckingPoint", "BackgroundError", "Observation", "ObservationError", -- 2.39.2