Trier un Sample

Chers développeurs,
Je cherche à trier simultanément les noeuds (de type Sample) et les poids (de type Point) d’un plan d’expériences (un WeightedExperiment) dans un code C++. Pour cela, je souhaite utiliser une méthode permettant d’obtenir les indices correspondants à l’ordre lexicographique. Le problème est que je n’arrive pas à trouver de méthode de la classe Sample permettant cela.
Pour contourner le problème en Python, j’ai utilisé numpy.argsort :

import openturns as ot
import numpy as np

ot.RandomGenerator.SetSeed(1)

size = 5
nodes = ot.Normal(2).getSample(size)
print("nodes =")
print(nodes)

weights = ot.Normal(1).getSample(size)
print("weights = ")
print(weights)

a = np.array(nodes)
indices = np.argsort(a[:, 0])
indices = [int(i) for i in indices]

sorted_nodes = nodes[indices]
print("sorted_nodes = ")
print(sorted_nodes)

sorted_weights = weights[indices]
print("sorted_weights = ")
print(sorted_weights)

Cela produit :

nodes =
    [ X0        X1        ]
0 : [  0.963648  0.952786 ]
1 : [ -1.66315   0.387699 ]
2 : [ -1.0859    0.779977 ]
3 : [  1.0941   -0.65186  ]
4 : [  1.58412   0.611992 ]
weights = 
    [ X0        ]
0 : [  0.81     ]
1 : [ -1.35994  ]
2 : [ -0.999924 ]
3 : [  2.40083  ]
4 : [ -0.817507 ]
sorted_nodes = 
    [ X0        X1        ]
0 : [ -1.66315   0.387699 ]
1 : [ -1.0859    0.779977 ]
2 : [  0.963648  0.952786 ]
3 : [  1.0941   -0.65186  ]
4 : [  1.58412   0.611992 ]
sorted_weights = 
    [ X0        ]
0 : [ -1.35994  ]
1 : [ -0.999924 ]
2 : [  0.81     ]
3 : [  2.40083  ]
4 : [ -0.817507 ]

Malheureusement, cela ne m’aide pas du tout en C++. Comment feriez-vous ?
Cordialement,
Michaël
PS
A la réflexion, il se pourrait que numpy.lexsort soit une meilleure réponse, mais cela ne répond pas à ma question en C++.

Bonsoir Michaël,

Tu peux utiliser la STL: std::sort sur un std::vector de std::pair contenant un Point et un Scalar. Tu fournis une fonction de comparaison entre tes paires (par défaut: l’ordre défini sur les clés, c’est-à dire l’ordre lexicographique pour des Point). Si tu regardes l’aide de ces différentes classes et de cet algorithme sur cppreference.com tu verras qu’il y a des exemples simples de mise en oeuvre. Tu peux également regarder dans le code d’OpenTURNS, par exemple dans KarhunenLoeveP1Algorithm::run() Il y a les lignes:

Collection< std::pair<Scalar, UnsignedInteger> > eigenPairs(augmentedDimension);
for (UnsignedInteger i = 0; i < augmentedDimension; ++i)
    eigenPairs[i] = std::pair<Scalar, UnsignedInteger>(-eigenValuesComplex[i].real(), i);

std::sort(eigenPairs.begin(), eigenPairs.end());

qui illustrent bien le propos. Si tu parcours ensuite la collection de std::pair<Point, Scalar>, alors first te permettra de récupérer les noeuds dans l’ordre lexicographique et second les poids associés

Tu pourrais également être intéressé par jeter un oeil sur std::unique pour supprimer les doublons, mais à mon avis il va falloir que tu l’implémentes toi-même pour pouvoir aggréger les poids.

A++

Régis

1 Like

Parfait, j’essaye : merci !

Michaël