Quelle structure pour stocker et chercher efficacement des points en N dimensions ?
Bonjour � toutes et � tous,
Je suis en train de coder une marche al�atoire (particuli�re) sur un graphe en n dimensions. Le marcheur doit se rappeler des n�uds (en n dimensions donc) qu'il a visit� par le pass� dans sa marche. L'id�e finale est de pouvoir �tudier certains comportements de cette marche sur un tr�s (tr�s) long terme, c'est � dire que la marcheur va visiter beaucoup beaucoup de n�uds qu'il devra garder en m�moire pour savoir s'il les a d�j� visit�.
Pour vous donner un ordre de grandeur, on doit pouvoir stocker 1e6 (million) ou 1e9 (milliard) de n�uds voire potentiellement plus. Mais dans un premier temps l'ordre de 1e6 peut convenir.
L'essentiel du calcul sera de savoir si, quand le marcheur arrive sur un n�ud, il a d�j� visit� ce n�ud. Il faut donc chercher dans une liste de n�uds visit�s potentiellement grande.
En regardant les structures de la STL (c++11) je me suis pench� sur le container std::unordered_set qui me parait int�ressant pour stocker des Points multidimensionnels. J'utilise une classe PointsND (propos�e ici: https://stackoverflow.com/questions/...le-point-class) que j'ai un peu adapt�e pour ma probl�matique en 2-dimensions dans un premier temps.
Code:
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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| class PointND
{
public:
PointND( const unsigned int dim )
{
//impossible location:
for (unsigned int i = 0; i < dim; i++)
elements_[i] = std::numeric_limits<double>::infinity();
}
//specific constructors for dimension 2:
PointND( const double x, const double y )
{
elements_[0] = x;
elements_[1] = y;
}
unsigned int n_dim() const {
return elements_.size();
}
double& operator [] ( unsigned const i )
{
return elements_[i];
}
double const& operator [] ( unsigned const i ) const
{
return elements_[i];
}
void operator += ( PointND const& other )
{
for( unsigned i = 0; i < nDimensions; ++i )
{
elements_[i] += other.elements_[i];
}
}
void operator -= ( PointND const& other )
{
for( unsigned i = 0; i < nDimensions; ++i )
{
elements_[i] -= other.elements_[i];
}
}
bool operator == ( PointND const& other )
{
for( unsigned i = 0; i < nDimensions; ++i )
if( elements_[i] != other.elements_[i] )
return false; //we found an error
return true; //otherwise return true;
}
friend PointND operator + ( PointND const& a, PointND const& b )
{
PointND ret( a );
ret += b;
return ret;
}
friend PointND operator - ( PointND const& a, PointND const& b )
{
PointND ret( a );
ret -= b;
return ret;
}
friend std::ostream &operator<<( std::ostream &out, const PointND * nd ) {
for(unsigned i = 0; i < nd->elements_.size()-1; i++)
out << nd->elements_[i] << ",";
out << nd->elements_[nd->elements_.size()-1];
return out;
}
private:
static const unsigned int nDimensions = 2; //default number of Dimensions is 2
std::array<double, nDimensions> elements_;
}; |
J'utilise donc std::unordered_set<PointND> visited. Et elements_[] contient en r�alit� des valeurs d'indexes d'un tableau en 2-dimensions, c'est-�-dire que je stocke des indices de noeuds (entiers, m�me si d�clar�s en double pour l'instant) [i,j] � valeurs dans -infini, +infini (m�me si en pratique on atteindra jamais ces infinis, on peut donc se contenter de tr�s grandes valeurs).
Ma question est la suivante: je dois fournir une fonction de hash qui soit bien r�partie sur le domaine des points en 2 dimensions. Que me sugg�riez vous comme fonction de hash?
Merci!