From e6e4038c0005476ce0e1a2092297f83446d3906e Mon Sep 17 00:00:00 2001 From: Jean-Philippe ARGAUD Date: Fri, 27 Oct 2023 11:45:13 +0200 Subject: [PATCH] Documentation update and method improvement --- ...thm_EnsembleOfSimulationGenerationTask.rst | 13 +++++---- ...thm_MeasurementsOptimalPositioningTask.rst | 13 +++++---- doc/en/ref_algorithm_SamplingTest.rst | 8 ++++-- doc/en/scripts/simple_3DVAR2.rst | 4 ++- doc/en/scripts/simple_3DVAR3.rst | 10 +++---- doc/en/scripts/tui_example_07.res | 2 ++ .../snippets/SampleAsMinMaxLatinHyperCube.rst | 13 +++++++++ ...thm_EnsembleOfSimulationGenerationTask.rst | 14 ++++++---- ...thm_MeasurementsOptimalPositioningTask.rst | 13 +++++---- doc/fr/ref_algorithm_SamplingTest.rst | 14 ++++++---- doc/fr/scripts/simple_3DVAR2.rst | 13 +++++---- doc/fr/scripts/simple_3DVAR3.rst | 6 ++--- doc/fr/scripts/tui_example_07.res | 2 ++ .../snippets/SampleAsMinMaxLatinHyperCube.rst | 14 ++++++++++ src/daComposant/daAlgorithms/Atoms/eosg.py | 13 +++++++-- .../EnsembleOfSimulationGenerationTask.py | 10 +++++-- .../MeasurementsOptimalPositioningTask.py | 10 +++++-- src/daComposant/daAlgorithms/SamplingTest.py | 19 ++++++++++--- src/daComposant/daCore/Aidsm.py | 2 ++ src/daComposant/daCore/BasicObjects.py | 7 ++++- src/daComposant/daCore/Interfaces.py | 5 ++-- src/daComposant/daCore/NumericObjects.py | 27 ++++++++++++++++++- 22 files changed, 178 insertions(+), 54 deletions(-) create mode 100644 doc/en/snippets/SampleAsMinMaxLatinHyperCube.rst create mode 100644 doc/fr/snippets/SampleAsMinMaxLatinHyperCube.rst diff --git a/doc/en/ref_algorithm_EnsembleOfSimulationGenerationTask.rst b/doc/en/ref_algorithm_EnsembleOfSimulationGenerationTask.rst index ab5743c..f5ee628 100644 --- a/doc/en/ref_algorithm_EnsembleOfSimulationGenerationTask.rst +++ b/doc/en/ref_algorithm_EnsembleOfSimulationGenerationTask.rst @@ -47,11 +47,12 @@ to the chosen homogeneous collection of state vectors :math:`\mathbf{x}` (available using the storable variable "*EnsembleOfStates*"). The sampling of the states :math:`\mathbf{x}` can be given explicitly or under -form of hyper-cubes, explicit or sampled according to classic distributions. -The computations are optimized according to the computer resources available -and the options requested by the user. Beware of the size of the hyper-cube -(and then to the number of computations) that can be reached, it can grow -quickly to be quite large. +form of hypercubes, explicit or sampled according to classic distributions, or +using Latin hypercube sampling (LHS). The computations are optimized according +to the computer resources available and the options requested by the user. +Beware of the size of the hypercube (and then to the number of computations) +that can be reached, it can grow quickly to be quite large. When a state is not +observable, a *"NaN"* value is returned. To be visible by the user while reducing the risk of storage difficulties, the results of sampling or simulations has to be **explicitly** asked for using the @@ -78,6 +79,8 @@ observations :math:`\mathbf{y}^o`. .. include:: snippets/SampleAsIndependantRandomVariables.rst +.. include:: snippets/SampleAsMinMaxLatinHyperCube.rst + .. include:: snippets/SampleAsMinMaxStepHyperCube.rst .. include:: snippets/SampleAsnUplet.rst diff --git a/doc/en/ref_algorithm_MeasurementsOptimalPositioningTask.rst b/doc/en/ref_algorithm_MeasurementsOptimalPositioningTask.rst index e115e18..d1f6ecd 100644 --- a/doc/en/ref_algorithm_MeasurementsOptimalPositioningTask.rst +++ b/doc/en/ref_algorithm_MeasurementsOptimalPositioningTask.rst @@ -77,11 +77,12 @@ There are two ways to use this algorithm: If the design of experiments is supplied, the sampling of the states :math:`\mathbf{x}` can be given as in the :ref:`section_ref_algorithm_EnsembleOfSimulationGenerationTask`, explicitly or -under form of hyper-cubes, explicit or sampled according to classic -distributions. The computations are optimized according to the computer -resources available and the options requested by the user. Beware of the size -of the hyper-cube (and then to the number of computations) that can be reached, -it can grow quickly to be quite large. +under form of hypercubes, explicit or sampled according to classic +distributions, or using Latin hypercube sampling (LHS). The computations are +optimized according to the computer resources available and the options +requested by the user. Beware of the size of the hypercube (and then to the +number of computations) that can be reached, it can grow quickly to be quite +large. .. _mop_determination: .. image:: images/mop_determination.png @@ -118,6 +119,8 @@ constrained positioning search. .. include:: snippets/SampleAsIndependantRandomVariables.rst +.. include:: snippets/SampleAsMinMaxLatinHyperCube.rst + .. include:: snippets/SampleAsMinMaxStepHyperCube.rst .. include:: snippets/SampleAsnUplet.rst diff --git a/doc/en/ref_algorithm_SamplingTest.rst b/doc/en/ref_algorithm_SamplingTest.rst index c585b57..be1dae3 100644 --- a/doc/en/ref_algorithm_SamplingTest.rst +++ b/doc/en/ref_algorithm_SamplingTest.rst @@ -41,8 +41,10 @@ This test is useful for analyzing the sensitivity of the functional :math:`J` to variations in the state :math:`\mathbf{x}` in particular. The sampling of the states :math:`\mathbf{x}` can be given explicitly or under -form of hyper-cubes, explicit or sampled according to classic distributions. -Beware of the size of the hyper-cube (and then to the number of computations) +form of hypercubes, explicit or sampled according to classic distributions, or +using Latin hypercube sampling (LHS). The computations are optimized according +to the computer resources available and the options requested by the user. +Beware of the size of the hypercube (and then to the number of computations) that can be reached, it can grow quickly to be quite large. When a state is not observable, a *"NaN"* value is returned. @@ -84,6 +86,8 @@ treatment during the calculation by well suited "*observer*". .. include:: snippets/SampleAsIndependantRandomVariables.rst +.. include:: snippets/SampleAsMinMaxLatinHyperCube.rst + .. include:: snippets/SampleAsMinMaxStepHyperCube.rst .. include:: snippets/SampleAsnUplet.rst diff --git a/doc/en/scripts/simple_3DVAR2.rst b/doc/en/scripts/simple_3DVAR2.rst index 56ce659..bef4a3e 100644 --- a/doc/en/scripts/simple_3DVAR2.rst +++ b/doc/en/scripts/simple_3DVAR2.rst @@ -5,7 +5,9 @@ The 3DVAR can also be used for a **time analysis of the observations of a given dynamic model**. In this case, the analysis is performed iteratively, at the arrival of each observation. For this example, we use the same simple dynamic system [Welch06]_ that is analyzed in the Kalman Filter -:ref:`section_ref_algorithm_KalmanFilter_examples`. +:ref:`section_ref_algorithm_KalmanFilter_examples`. For a good understanding of +time management, please refer to the :ref:`schema_d_AD_temporel` and the +explanations in the section :ref:`section_theory_dynamic`. At each step, the classical 3DVAR analysis updates only the state of the system. By modifying the *a priori* covariance values with respect to the diff --git a/doc/en/scripts/simple_3DVAR3.rst b/doc/en/scripts/simple_3DVAR3.rst index 0d6e9a5..91b098c 100644 --- a/doc/en/scripts/simple_3DVAR3.rst +++ b/doc/en/scripts/simple_3DVAR3.rst @@ -7,15 +7,15 @@ the background errors during the iterations. This update is an **assumption** of the user, and there are multiple alternatives that will depend on the physics of the case. We illustrate one of them here. -We choose, in an arbitrary way, to make the *a priori* covariance of the +We choose, in an **arbitrary way**, to make the *a priori* covariance of the background errors to decrease by a constant factor :math:`0.9^2=0.81` as long as it remains above a limit value of :math:`0.1^2=0.01` (which is the fixed value of *a priori* covariance of the background errors of the previous example), knowing that it starts at the value `1` (which is the fixed value of *a priori* covariance of the background errors used for the first step of -Kalman filtering). This value is updated at each step, by reinjecting it as the -*a priori* covariance of the state which is used as a background in the next -step of analysis, in an explicit loop. +Kalman filtering). This value is updated at each step, by re-injecting it as +the *a priori* covariance of the state which is used as a background in the +next step of analysis, in an explicit loop. We notice in this case that the state estimation converges faster to the true value, and that the assimilation then behaves similarly to the examples for the @@ -26,6 +26,6 @@ force the decrease of the *a priori* covariance. .. note:: We insist on the fact that the *a priori* covariance variations, which - determine the *a posteriori* covariance variations, are a **user + determine the *a posteriori* covariance variations, are a **user arbitrary assumption** and not an obligation. This assumption must therefore be **adapted to the physical case**. diff --git a/doc/en/scripts/tui_example_07.res b/doc/en/scripts/tui_example_07.res index a39599b..c7c6d4d 100644 --- a/doc/en/scripts/tui_example_07.res +++ b/doc/en/scripts/tui_example_07.res @@ -2,6 +2,8 @@ ADAO Study report ================================================================================ +Summary build with ADAO version 9.12.0 + - AlgorithmParameters command has been set with values: Algorithm = '3DVAR' diff --git a/doc/en/snippets/SampleAsMinMaxLatinHyperCube.rst b/doc/en/snippets/SampleAsMinMaxLatinHyperCube.rst new file mode 100644 index 0000000..4af5700 --- /dev/null +++ b/doc/en/snippets/SampleAsMinMaxLatinHyperCube.rst @@ -0,0 +1,13 @@ +.. index:: single: SampleAsMinMaxLatinHyperCube + +SampleAsMinMaxLatinHyperCube + *List of triplets of pair values*. This key describes the bounded domain in + which the calculations points will be placed, from a *[min,max]* pair for + each state component. The lower bounds are included. This list of pairs, + identical in number to the size of the state space, is augmented by a pair of + integers *[dim,nb]* containing the dimension of the state space and the + desired number of sample points. Sampling is then automatically constructed + using the Latin hypercube method (LHS). + + Example : + ``{"SampleAsMinMaxLatinHyperCube":[[0.,1.],[-1,3]]+[[2,11]]}`` for a state space of dimension 2 and 11 sampling points diff --git a/doc/fr/ref_algorithm_EnsembleOfSimulationGenerationTask.rst b/doc/fr/ref_algorithm_EnsembleOfSimulationGenerationTask.rst index 18a8b12..de32ba7 100644 --- a/doc/fr/ref_algorithm_EnsembleOfSimulationGenerationTask.rst +++ b/doc/fr/ref_algorithm_EnsembleOfSimulationGenerationTask.rst @@ -48,11 +48,13 @@ choisie de vecteurs d'états :math:`\mathbf{x}` (disponible à l'aide de la variable stockable "*EnsembleOfStates*"). L'échantillonnage des états :math:`\mathbf{x}` peut être fourni explicitement -ou sous la forme d'hyper-cubes, explicites ou échantillonnés selon des -distributions courantes. Les calculs sont optimisés selon les ressources -informatiques disponibles et les options demandées par l'utilisateur. Attention -à la taille de l'hyper-cube (et donc au nombre de calculs) qu'il est possible -d'atteindre, elle peut rapidement devenir importante. +ou sous la forme d'hypercubes, explicites ou échantillonnés selon des +distributions courantes, ou à l'aide d'un échantillonnage par hypercube latin +(LHS). Les calculs sont optimisés selon les ressources informatiques +disponibles et les options demandées par l'utilisateur. Attention à la taille +de l'hypercube (et donc au nombre de calculs) qu'il est possible d'atteindre, +elle peut rapidement devenir importante. Lorsqu'un état n'est pas observable, +une valeur *"NaN"* est retournée. Pour apparaître pour l'utilisateur tout en réduisant les difficultés de stockage, les résultats de l'échantillonnage ou des simulations doivent être @@ -79,6 +81,8 @@ d'échantillonnage pour établir un ensemble de valeurs de fonctionnelle d'erreu .. include:: snippets/SampleAsIndependantRandomVariables.rst +.. include:: snippets/SampleAsMinMaxLatinHyperCube.rst + .. include:: snippets/SampleAsMinMaxStepHyperCube.rst .. include:: snippets/SampleAsnUplet.rst diff --git a/doc/fr/ref_algorithm_MeasurementsOptimalPositioningTask.rst b/doc/fr/ref_algorithm_MeasurementsOptimalPositioningTask.rst index 9ee7b93..27ae90b 100644 --- a/doc/fr/ref_algorithm_MeasurementsOptimalPositioningTask.rst +++ b/doc/fr/ref_algorithm_MeasurementsOptimalPositioningTask.rst @@ -80,11 +80,12 @@ Il y a deux manières d'utiliser cet algorithme: Dans le cas où l'on fournit le plan d'expérience, l'échantillonnage des états :math:`\mathbf{x}` peut être fourni comme pour un :ref:`section_ref_algorithm_EnsembleOfSimulationGenerationTask`, explicitement -ou sous la forme d'hyper-cubes, explicites ou échantillonnés selon des -distributions courantes. Les calculs sont optimisés selon les ressources -informatiques disponibles et les options demandées par l'utilisateur. Attention -à la taille de l'hyper-cube (et donc au nombre de calculs) qu'il est possible -d'atteindre, elle peut rapidement devenir importante. +ou sous la forme d'hypercubes, explicites ou échantillonnés selon des +distributions courantes, ou à l'aide d'un échantillonnage par hypercube latin +(LHS). Les calculs sont optimisés selon les ressources informatiques +disponibles et les options demandées par l'utilisateur. Attention à la taille +de l'hypercube (et donc au nombre de calculs) qu'il est possible d'atteindre, +elle peut rapidement devenir importante. .. _mop_determination: .. image:: images/mop_determination.png @@ -121,6 +122,8 @@ d'analyse pour une recherche de positionnement contraint. .. include:: snippets/SampleAsIndependantRandomVariables.rst +.. include:: snippets/SampleAsMinMaxLatinHyperCube.rst + .. include:: snippets/SampleAsMinMaxStepHyperCube.rst .. include:: snippets/SampleAsnUplet.rst diff --git a/doc/fr/ref_algorithm_SamplingTest.rst b/doc/fr/ref_algorithm_SamplingTest.rst index dc20b3d..f88a875 100644 --- a/doc/fr/ref_algorithm_SamplingTest.rst +++ b/doc/fr/ref_algorithm_SamplingTest.rst @@ -42,11 +42,13 @@ Ce test est utile pour analyser la sensibilité de la fonctionnelle :math:`J` aux variations de l'état :math:`\mathbf{x}` en particulier. L'échantillonnage des états :math:`\mathbf{x}` peut être fourni explicitement -ou sous la forme d'hyper-cubes, explicites ou échantillonnés selon des -distributions courantes. Attention à la taille de l'hyper-cube (et donc au -nombre de calculs) qu'il est possible d'atteindre, elle peut rapidement devenir -importante. Lorsqu'un état n'est pas observable, une valeur *"NaN"* est -retournée. +ou sous la forme d'hypercubes, explicites ou échantillonnés selon des +distributions courantes, ou à l'aide d'un échantillonnage par hypercube latin +(LHS). Les calculs sont optimisés selon les ressources informatiques +disponibles et les options demandées par l'utilisateur. Attention à la taille +de l'hypercube (et donc au nombre de calculs) qu'il est possible d'atteindre, +elle peut rapidement devenir importante. Lorsqu'un état n'est pas observable, +une valeur *"NaN"* est retournée. Il est aussi possible de fournir un ensemble de simulations :math:`\mathbf{y}` déjà établies par ailleurs (donc sans besoin explicite d'un opérateur @@ -87,6 +89,8 @@ calcul à l'aide des "*observer*" adaptés. .. include:: snippets/SampleAsIndependantRandomVariables.rst +.. include:: snippets/SampleAsMinMaxLatinHyperCube.rst + .. include:: snippets/SampleAsMinMaxStepHyperCube.rst .. include:: snippets/SampleAsnUplet.rst diff --git a/doc/fr/scripts/simple_3DVAR2.rst b/doc/fr/scripts/simple_3DVAR2.rst index 524adc1..a92d21b 100644 --- a/doc/fr/scripts/simple_3DVAR2.rst +++ b/doc/fr/scripts/simple_3DVAR2.rst @@ -5,7 +5,10 @@ Le 3DVAR peut aussi être utilisé pour une **analyse temporelle des observation d'un modèle dynamique donné**. Dans ce cas, l'analyse est conduite de manière itérative, lors de l'arrivée de chaque observation. On utilise pour cet exemple le même système dynamique simple [Welch06]_ que celui qui est analysé dans les -:ref:`section_ref_algorithm_KalmanFilter_examples` du Filtre de Kalman. +:ref:`section_ref_algorithm_KalmanFilter_examples` du Filtre de Kalman. Pour +une bonne compréhension de la gestion du temps, on se reportera au +:ref:`schema_d_AD_temporel` et aux explications décrites dans la section pour +:ref:`section_theory_dynamic`. A chaque étape, l'analyse 3DVAR classique remet à jour uniquement l'état du système. Moyennant une modification des valeurs de covariances *a priori* par @@ -19,7 +22,7 @@ manière ici un peu plus lente qu'avec un Filtre de Kalman. l'analyse itérative 3DVAR remet à jour uniquement l'état et non pas sa covariance. Comme les hypothèses d'opérateurs et de covariance *a priori* restent inchangées ici au cours de l'évolution, la covariance *a - posteriori* est constante. Le tracé qui suit de cette covariance *a - posteriori* permet d'insister sur cette propriété tout à fait attendue de - l'analyse 3DVAR. Une hypothèse plus évoluée est proposée dans l'exemple qui - suit. + posteriori* est constante. Le tracé de cette covariance *a posteriori*, sur + la seconde figure qui suit, permet d'insister sur cette propriété tout à + fait attendue de l'analyse 3DVAR. Une hypothèse plus évoluée est proposée + dans l'exemple d'après. diff --git a/doc/fr/scripts/simple_3DVAR3.rst b/doc/fr/scripts/simple_3DVAR3.rst index deabaea..7f53db4 100644 --- a/doc/fr/scripts/simple_3DVAR3.rst +++ b/doc/fr/scripts/simple_3DVAR3.rst @@ -7,7 +7,7 @@ des erreurs d'ébauche au cours des itérations. Cette remise à jour est une **hypothèse** de l'utilisateur, et il y a de multiples possibilités qui vont dépendre de la physique du cas. On en illustre une ici. -On choisit, arbitrairement, de faire décroître la covariance *a priori* des +On choisit, **arbitrairement**, de faire décroître la covariance *a priori* des erreurs d'ébauche d'un facteur constant :math:`0.9^2=0.81` tant qu'elle reste supérieure à une valeur limite de :math:`0.1^2=0.01` (qui est la valeur fixe de covariance *a priori* des erreurs d'ébauche de l'exemple précédent), sachant @@ -28,5 +28,5 @@ décroissance de la covariance *a priori*. On insiste sur le fait que les variations de covariance *a priori*, qui conditionnent les variations de covariance *a posteriori*, relèvent d'une - **hypothèse utilisateur** et non pas d'une obligation. Cette hypothèse doit - donc être **adaptée en fonction du cas physique**. + **hypothèse arbitraire de l'utilisateur** et non pas d'une obligation. + Cette hypothèse doit donc être **adaptée en fonction du cas physique**. diff --git a/doc/fr/scripts/tui_example_07.res b/doc/fr/scripts/tui_example_07.res index a39599b..c7c6d4d 100644 --- a/doc/fr/scripts/tui_example_07.res +++ b/doc/fr/scripts/tui_example_07.res @@ -2,6 +2,8 @@ ADAO Study report ================================================================================ +Summary build with ADAO version 9.12.0 + - AlgorithmParameters command has been set with values: Algorithm = '3DVAR' diff --git a/doc/fr/snippets/SampleAsMinMaxLatinHyperCube.rst b/doc/fr/snippets/SampleAsMinMaxLatinHyperCube.rst new file mode 100644 index 0000000..e9684c2 --- /dev/null +++ b/doc/fr/snippets/SampleAsMinMaxLatinHyperCube.rst @@ -0,0 +1,14 @@ +.. index:: single: SampleAsMinMaxLatinHyperCube + +SampleAsMinMaxLatinHyperCube + *Liste de triplets de paires réelles*. Cette clé décrit le domaine borné dans + lequel les points de calcul seront placés, sous la forme d'une paire + *[min,max]* pour chaque composante de l'état. Les bornes inférieures sont + incluses. Cette liste de paires, en nombre identique à la taille de l'espace + des états, est complétée par une paire d'entier *[dim,nb]* comportant la + dimension de l'espace des états et le nombre souhaité de points + d'échantillonnage. L'échantillonnage est ensuite construit automatiquement + selon la méthode de l'hypercube Latin (LHS). + + Exemple : + ``{"SampleAsMinMaxLatinHyperCube":[[0.,1.],[-1,3]]+[[2,11]]}`` pour un espace d'état de dimension 2 et 11 points d'échantillonnage diff --git a/src/daComposant/daAlgorithms/Atoms/eosg.py b/src/daComposant/daAlgorithms/Atoms/eosg.py index e29ac5d..2204cd1 100644 --- a/src/daComposant/daAlgorithms/Atoms/eosg.py +++ b/src/daComposant/daAlgorithms/Atoms/eosg.py @@ -38,9 +38,16 @@ def eosg(selfA, Xb, HO, outputEOX = False, assumeNoFailure = True): selfA._parameters["SampleAsnUplet"], selfA._parameters["SampleAsExplicitHyperCube"], selfA._parameters["SampleAsMinMaxStepHyperCube"], + selfA._parameters["SampleAsMinMaxLatinHyperCube"], selfA._parameters["SampleAsIndependantRandomVariables"], Xb, + selfA._parameters["SetSeed"], ) + # + if hasattr(sampleList,"__len__") and len(sampleList) == 0: + if outputEOX: return numpy.array([[]]), numpy.array([[]]) + else: return numpy.array([[]]) + # if outputEOX or selfA._toStore("EnsembleOfStates"): EOX = numpy.stack(tuple(copy.copy(sampleList)), axis=1) # @@ -88,13 +95,15 @@ def eosg(selfA, Xb, HO, outputEOX = False, assumeNoFailure = True): # ---------- # if selfA._toStore("EnsembleOfStates"): - assert EOX.shape[1] == EOS.shape[1], " Error of number of states in Ensemble Of Simulations Generation" + if EOX.shape[1] != EOS.shape[1]: + raise ValueError("Numbers of states (=%i) and snapshots (=%i) has to be the same!"%(EOX.shape[1], EOS.shape[1])) selfA.StoredVariables["EnsembleOfStates"].store( EOX ) if selfA._toStore("EnsembleOfSimulations"): selfA.StoredVariables["EnsembleOfSimulations"].store( EOS ) # if outputEOX: - assert EOX.shape[1] == EOS.shape[1], " Error of number of states in Ensemble Of Simulations Generation" + if EOX.shape[1] != EOS.shape[1]: + raise ValueError("Numbers of states (=%i) and snapshots (=%i) has to be the same!"%(EOX.shape[1], EOS.shape[1])) return EOX, EOS else: return EOS diff --git a/src/daComposant/daAlgorithms/EnsembleOfSimulationGenerationTask.py b/src/daComposant/daAlgorithms/EnsembleOfSimulationGenerationTask.py index 4f94c24..d22a5f3 100644 --- a/src/daComposant/daAlgorithms/EnsembleOfSimulationGenerationTask.py +++ b/src/daComposant/daAlgorithms/EnsembleOfSimulationGenerationTask.py @@ -38,13 +38,19 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): name = "SampleAsExplicitHyperCube", default = [], typecast = tuple, - message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages de chaque variable comme une liste", + message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages explicites de chaque variable comme une liste", ) self.defineRequiredParameter( name = "SampleAsMinMaxStepHyperCube", default = [], typecast = tuple, - message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages de chaque variable par un triplet [min,max,step]", + message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages implicites de chaque variable par un triplet [min,max,step]", + ) + self.defineRequiredParameter( + name = "SampleAsMinMaxLatinHyperCube", + default = [], + typecast = tuple, + message = "Points de calcul définis par un hyper-cube Latin dont on donne les bornes de chaque variable par une paire [min,max], suivi du nombre de points demandés", ) self.defineRequiredParameter( name = "SampleAsIndependantRandomVariables", diff --git a/src/daComposant/daAlgorithms/MeasurementsOptimalPositioningTask.py b/src/daComposant/daAlgorithms/MeasurementsOptimalPositioningTask.py index f434b4c..2cae2a6 100644 --- a/src/daComposant/daAlgorithms/MeasurementsOptimalPositioningTask.py +++ b/src/daComposant/daAlgorithms/MeasurementsOptimalPositioningTask.py @@ -89,13 +89,19 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): name = "SampleAsExplicitHyperCube", default = [], typecast = tuple, - message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages de chaque variable comme une liste", + message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages explicites de chaque variable comme une liste", ) self.defineRequiredParameter( name = "SampleAsMinMaxStepHyperCube", default = [], typecast = tuple, - message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages de chaque variable par un triplet [min,max,step]", + message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages implicites de chaque variable par un triplet [min,max,step]", + ) + self.defineRequiredParameter( + name = "SampleAsMinMaxLatinHyperCube", + default = [], + typecast = tuple, + message = "Points de calcul définis par un hyper-cube Latin dont on donne les bornes de chaque variable par une paire [min,max], suivi du nombre de points demandés", ) self.defineRequiredParameter( name = "SampleAsIndependantRandomVariables", diff --git a/src/daComposant/daAlgorithms/SamplingTest.py b/src/daComposant/daAlgorithms/SamplingTest.py index 9c7304c..ecc9646 100644 --- a/src/daComposant/daAlgorithms/SamplingTest.py +++ b/src/daComposant/daAlgorithms/SamplingTest.py @@ -46,13 +46,19 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): name = "SampleAsExplicitHyperCube", default = [], typecast = tuple, - message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages de chaque variable comme une liste", + message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages explicites de chaque variable comme une liste", ) self.defineRequiredParameter( name = "SampleAsMinMaxStepHyperCube", default = [], typecast = tuple, - message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages de chaque variable par un triplet [min,max,step]", + message = "Points de calcul définis par un hyper-cube dont on donne la liste des échantillonnages implicites de chaque variable par un triplet [min,max,step]", + ) + self.defineRequiredParameter( + name = "SampleAsMinMaxLatinHyperCube", + default = [], + typecast = tuple, + message = "Points de calcul définis par un hyper-cube Latin dont on donne les bornes de chaque variable par une paire [min,max], suivi de la paire [dimension, nombre de points demandés]", ) self.defineRequiredParameter( name = "SampleAsIndependantRandomVariables", @@ -174,11 +180,18 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): self._parameters["SampleAsnUplet"], self._parameters["SampleAsExplicitHyperCube"], self._parameters["SampleAsMinMaxStepHyperCube"], + self._parameters["SampleAsMinMaxLatinHyperCube"], self._parameters["SampleAsIndependantRandomVariables"], Xb, + self._parameters["SetSeed"], ) - EOX = numpy.stack(tuple(copy.copy(sampleList)), axis=1) + if hasattr(sampleList,"__len__") and len(sampleList) == 0: + EOX = numpy.array([[]]) + else: + EOX = numpy.stack(tuple(copy.copy(sampleList)), axis=1) EOS = self._parameters["EnsembleOfSnapshots"] + if EOX.shape[1] != EOS.shape[1]: + raise ValueError("Numbers of states (=%i) and snapshots (=%i) has to be the same!"%(EOX.shape[1], EOS.shape[1])) # if self._toStore("EnsembleOfStates"): self.StoredVariables["EnsembleOfStates"].store( EOX ) diff --git a/src/daComposant/daCore/Aidsm.py b/src/daComposant/daCore/Aidsm.py index f581670..00f629a 100644 --- a/src/daComposant/daCore/Aidsm.py +++ b/src/daComposant/daCore/Aidsm.py @@ -35,6 +35,7 @@ from daCore.BasicObjects import AlgorithmAndParameters, DataObserver from daCore.BasicObjects import RegulationAndParameters, CaseLogger from daCore.BasicObjects import UserScript, ExternalParameters from daCore import PlatformInfo +from daCore import version # from daCore import ExtendedLogging ; ExtendedLogging.ExtendedLogging() # A importer en premier import logging @@ -486,6 +487,7 @@ class Aidsm(object): self.__case.register("setDebug",dir(),locals()) log = logging.getLogger() log.setLevel( __level ) + logging.debug("Mode debug initialisé avec %s %s"%(version.name, version.version)) self.__StoredInputs["Debug"] = __level self.__StoredInputs["NoDebug"] = False return 0 diff --git a/src/daComposant/daCore/BasicObjects.py b/src/daComposant/daCore/BasicObjects.py index ce6314f..7977635 100644 --- a/src/daComposant/daCore/BasicObjects.py +++ b/src/daComposant/daCore/BasicObjects.py @@ -34,7 +34,9 @@ import time import numpy import warnings from functools import partial -from daCore import Persistence, PlatformInfo, Interfaces +from daCore import Persistence +from daCore import PlatformInfo +from daCore import Interfaces from daCore import Templates # ============================================================================== @@ -1101,6 +1103,9 @@ class Algorithm(object): elif not (listval is not None and __val in listval) and not (listadv is not None and __val in listadv): raise ValueError("The value '%s' is not allowed for the parameter named '%s', it has to be in the list %s."%( __val, __k,listval)) # + if __k in ["SetSeed",]: + __val = value + # return __val def requireInputArguments(self, mandatory=(), optional=()): diff --git a/src/daComposant/daCore/Interfaces.py b/src/daComposant/daCore/Interfaces.py index 3b65b80..37ff99b 100644 --- a/src/daComposant/daCore/Interfaces.py +++ b/src/daComposant/daCore/Interfaces.py @@ -36,6 +36,7 @@ from daCore import Persistence from daCore import PlatformInfo from daCore import Templates from daCore import Reporting +from daCore import version # ============================================================================== class GenericCaseViewer(object): @@ -675,6 +676,7 @@ class _ReportViewer(GenericCaseViewer): self._r.append("ADAO Study report", "title") else: self._r.append(str(self._name), "title") + self._r.append("Summary build with %s version %s"%(version.name, version.version)) if self._content is not None: for command in self._content: self._append(*command) @@ -683,8 +685,7 @@ class _ReportViewer(GenericCaseViewer): "Transformation d'une commande individuelle en un enregistrement" if __command is not None and __keys is not None and __local is not None: if __command in ("set","get") and "Concept" in __keys: __command = __local["Concept"] - __text = "" - __text += "%s command has been set"%str(__command.replace("set","")) + __text = "%s command has been set"%str(__command.replace("set","")) __ktext = "" for k in __keys: if k not in __local: continue diff --git a/src/daComposant/daCore/NumericObjects.py b/src/daComposant/daCore/NumericObjects.py index 429cf14..ab2cee4 100644 --- a/src/daComposant/daCore/NumericObjects.py +++ b/src/daComposant/daCore/NumericObjects.py @@ -27,7 +27,7 @@ __author__ = "Jean-Philippe ARGAUD" import os, copy, types, sys, logging, math, numpy, itertools from daCore.BasicObjects import Operator, Covariance, PartialAlgorithm -from daCore.PlatformInfo import PlatformInfo, vfloat +from daCore.PlatformInfo import PlatformInfo, vt, vfloat mpr = PlatformInfo().MachinePrecision() mfp = PlatformInfo().MaximumPrecision() # logging.getLogger().setLevel(logging.DEBUG) @@ -1036,8 +1036,10 @@ def BuildComplexSampleList( __SampleAsnUplet, __SampleAsExplicitHyperCube, __SampleAsMinMaxStepHyperCube, + __SampleAsMinMaxLatinHyperCube, __SampleAsIndependantRandomVariables, __X0, + __Seed = None, ): # --------------------------- if len(__SampleAsnUplet) > 0: @@ -1045,8 +1047,10 @@ def BuildComplexSampleList( for i,Xx in enumerate(sampleList): if numpy.ravel(Xx).size != __X0.size: raise ValueError("The size %i of the %ith state X in the sample and %i of the checking point Xb are different, they have to be identical."%(numpy.ravel(Xx).size,i+1,X0.size)) + # --------------------------- elif len(__SampleAsExplicitHyperCube) > 0: sampleList = itertools.product(*list(__SampleAsExplicitHyperCube)) + # --------------------------- elif len(__SampleAsMinMaxStepHyperCube) > 0: coordinatesList = [] for i,dim in enumerate(__SampleAsMinMaxStepHyperCube): @@ -1055,6 +1059,27 @@ def BuildComplexSampleList( else: coordinatesList.append(numpy.linspace(dim[0],dim[1],1+int((float(dim[1])-float(dim[0]))/float(dim[2])))) sampleList = itertools.product(*coordinatesList) + # --------------------------- + elif len(__SampleAsMinMaxLatinHyperCube) > 0: + import scipy, warnings + if vt(scipy.version.version) <= vt("1.7.0"): + __msg = "In order to use Latin Hypercube sampling, you must at least use Scipy version 1.7.0 (and you are presently using Scipy %s). A void sample is then generated."%scipy.version.version + warnings.warn(__msg, FutureWarning, stacklevel=50) + coordinatesList = [] + else: + __spDesc = list(__SampleAsMinMaxLatinHyperCube) + __nbSamp = int(__spDesc.pop()[1]) + __sample = scipy.stats.qmc.LatinHypercube( + d = len(__spDesc), + seed = numpy.random.default_rng(__Seed), + ) + __sample = __sample.random(n = __nbSamp) + __bounds = numpy.array(__spDesc)[:,0:2] + l_bounds = __bounds[:,0] + u_bounds = __bounds[:,1] + coordinatesList = scipy.stats.qmc.scale(__sample, l_bounds, u_bounds) + sampleList = coordinatesList + # --------------------------- elif len(__SampleAsIndependantRandomVariables) > 0: coordinatesList = [] for i,dim in enumerate(__SampleAsIndependantRandomVariables): -- 2.30.2