IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

ensembles discrets et système d'indiçage


Sujet :

C++

  1. #1
    Membre averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut ensembles discrets et système d'indiçage
    Salut à toutes et à tous!

    J'ai souvent le problème de devoir mapper un ensemble discret X vers les entiers naturels N grâce une relation d'ordre, pour pouvoir utiliser des structures qui fonctionnent avec des indices (matrices, vecteurs etc).

    Par exemple quand je calcule des distances élément par élément d'un ensemble X, j'ai envie de stocker ces valeurs dans une matrice que je planque derrière une petite classe PairwiseMatrix, ce qui revient à devoir attribuer un indice (un peu arbitraire) à chaque élément de X. Si j'ai envie d'accéder plus tard à la distance entre deux éléments a et b de X, je dois retrouver les indices correspondants avec une code du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    class PairwiseMatrix {
     
      // Constructeur pour calculer f(a,b) pour tout couple a,b appartenant à X^2
      // Les indices sont donnés par l'ordre des points dans le vecteur p
      Pariwise(std::vector<T> const& p, F f):
      m_points(p),
      m_matrix(construct_matrix(p, f))
      {}
     
    unsigned int ID(T const& x) const {
        auto it = std::find(m_points.begin(), m_points.end(), x); // m_points conserve l'ordre des éléments donné à la construction avec un std::vector
        assert( it != m_points.end());
        return std::distance(m_points.begin(), it);
      }
     
      auto operator()(T const& x, T const& y) const {
        return m_matrix(ID(x),ID(y));
      }
     
    }
    Si c'est limité à une seule classe, ça va. Le truc c'est que ce genre de code pour switcher entre X et N commence à se retrouve partout dans le projet. C'est normal/préoccupant/lourd ?

    J'hésite à ordonner le vecteur d'éléments de X une bonne fois pour toute dès le début du code, et ne concevoir le reste de la bibliothèque que pour des éléments de type intégral.

    Ca revient à buter pas mal de boulot (à la qualité discutable, comme vous le voyez).

    Que me conseillez-vous, et comment vous y prenez vous habituellement ?

    Merci
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    La première question que j'aurais envie de te poser, c'est : ta matrice sera-t-elle a priori constante (ou rarement mise à jour) ou sera-t-elle au contraire régulièrement mise à jour

    Note que je pourrais poser la question différemment : sachant que ce que tu "gagnes" d'un coté, tu le "perds" forcément de l'autre (tu ne pourras réellement gagner du temps sur la recherche d'un élément que si tu "perds un peu de temps" sur la mise à jour, et vice versa), sur quel aspect préfères tu "perdre du temps" pour gagner du temps sur l'autre aspect

    Car, a priori, tout partira de ce choix "cornélien" :

    Si tu fais une mise à jour de temps en temps (fut-elle "complète" ou non), tu préférera que la recherche se fasse rapidement, quitte à "perdre un maximum de temps" lors de la mise à jour.

    A l'inverse, si tu fais de nombreuses mises à jour de ta matrices pour très peux de recherches, tu préféreras sans doute que la recherche soit "(très) lente", mais que la mise à jour soit "la plus rapide possible".

    Et, forcément, les structures et les algorithmes que tu pourras mettre en place refléteront clairement ce "choix de base".

    Je ne crois pas qu'il soit possible de te conseiller tant que tu n'auras pas clairement établi tes priorités à ce niveau là ... même sije peux aussi me tromper sur ce coup
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 107
    Points
    6 107
    Par défaut
    Salut,

    Si tu as seulement besoin de numéroter tes points de manière arbitraire et que tu veux éviter que la recherche du numéro d'un point soit coûteuse, alors il suffit de travailler directement avec un type qui contient à la fois un point et son numéro sur place :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class PointWithId {
    public:
    	...
    	Point  getPoint() const { return m_point; }
    	size_t getId()    const { return m_id; }
    	...
    private:
    	Point  m_point;
    	size_t m_id;
    };
    Ainsi, quand tu veux récupérer la distance entre deux points via ta matrice des distances, il te suffit d'appeler getId() sur tes deux points puis de récupérer la distance correspondante à cette paire de numéros.

    Si de plus tes points sont ordonnés dans un vecteur qui ne change pas alors, pour t'assurer que les numéros de tes points soient cohérents, tu pourrais remplacer m_id par la position du point dans le vecteur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class PointWithId {
    public:
    	// ...
    	Point  getPoint() const { return m_vector[m_index]; }
    	size_t getId()    const { return m_index; }
    	// ...
    private:
    	std::vector<Point> const& m_vector;
    	size_t                    m_index;
    };
    Mais ce n'est qu'un détail d'implémentation. Je pense que le code qui gère la matrice des distances ne devrait pas dépendre du fait que les points soient stockés dans un vecteur. Tout ce que ce code devrait savoir, c'est que les numéros de tes points vont de 0 à la taille de la matrice moins un.

    Voici un bout de code plus complet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    #include <algorithm>
    #include <cassert>
    #include <vector>
     
    class Point {
    public:
    	Point(double x, double y) :
    		m_x{x}, m_y{y}
    	{}
     
    	double getX() const { return m_x; }
    	double getY() const { return m_y; }
     
    	bool operator==(Point const& other) const {
    		return m_x == other.m_x && m_y == other.m_y;
    	}
    	bool operator!=(Point const& other) const {
    		return !(*this == other);
    	}
     
    private:
    	double m_x;
    	double m_y;
    };
     
    size_t getIndexOfPointInVector(Point const& p, std::vector<Point> const& vect) {
    	auto it = std::find(vect.begin(), vect.end(), p);
    	assert(it != vect.end());
    	return std::distance(vect.begin(), it);
    }
     
    class PointWithId {
    public:
    	PointWithId(std::vector<Point> const& vect, size_t index) :
    		m_vector{vect}, m_index{index}
    	{}
    	PointWithId(std::vector<Point> const& vect, Point const& p) :
    		m_vector{vect}, m_index{getIndexOfPointInVector(p, vect)}
    	{}
     
    	Point  getPoint() const { return m_vector[m_index]; }
    	size_t getId()    const { return m_index; }
    	double getX()     const { return getPoint().getX(); }
    	double getY()     const { return getPoint().getY(); }
     
    	bool operator==(PointWithId const& other) const {
    		return getPoint() == other.getPoint();
    	}
    	bool operator!=(PointWithId const& other) const {
    		return !(*this == other);
    	}
     
    private:
    	std::vector<Point> const& m_vector;
    	size_t                    m_index;
    };
    Remarque : l'interface de PointWithId est volontairement proche de celle de Point afin que l'on puisse facilement changer le code en remplaçant des Point par des PointWithId.

  4. #4
    Membre averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut
    Encore une fois, merci à vous deux pour vos réponses toujours aussi pertinentes

    Citation Envoyé par koala01 Voir le message
    Salut,
    La première question que j'aurais envie de te poser, c'est : ta matrice sera-t-elle a priori constante (ou rarement mise à jour) ou sera-t-elle au contraire régulièrement mise à jour
    Ca dépend.

    -- La matrice des distances est construite une seule fois.
    -- On rentre ensuite dans une grosse boucle de simulation (environ 10^6 reps)
    ----La matrice est copiée et une transformation est appliquée à chacun des termes
    ----Ensuite il y a deux grosses stratégies:
    ------ option A: Les nouveaux coefficients sont soit transmis à des distributions discrètes de la STL pour pouvoir échantillonner un point d'arrivée conditionnellement à un point de départ
    ------ option B: Les termes de la matrice sont utilisés pour multiplier un vecteur de valeurs


    Citation Envoyé par koala01 Voir le message
    Salut,
    Et, forcément, les structures et les algorithmes que tu pourras mettre en place refléteront clairement ce "choix de base".
    Je ne crois pas qu'il soit possible de te conseiller tant que tu n'auras pas clairement établi tes priorités à ce niveau là
    Moui c'est en général à ce moment que je viens papoter ici: quand c'est le bazar dans mes priorités ahaha ! C'est plus clair maintenant merci

    Pyramidev, je crois que c'est effectivement quelque chose du genre dont j'avais besoin... J'avais bien pensé à "externaliser" le vecteur, mais pas comme ça. Ca a effectivement l'air beaucoup plus léger, tu relègues tout ce qui concerne l'indiçage à cette petite classe PointWithID waaaah
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 28/05/2015, 09h42
  2. régulation d'un système continu par un régulateur discret
    Par arbas dans le forum Mathématiques
    Réponses: 3
    Dernier message: 03/11/2010, 10h20
  3. [Débutant] dstep >> Réponse à un échelon d'un système discret
    Par bastou93 dans le forum Signal
    Réponses: 1
    Dernier message: 21/10/2010, 11h46
  4. Réponses: 3
    Dernier message: 12/06/2002, 19h03
  5. IA avec le système de note
    Par scorpiwolf dans le forum C
    Réponses: 4
    Dernier message: 06/05/2002, 12h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo