VectorXd and std::set: duplicate elements

393 Views Asked by At

I'm trying to use std::set together with VectorXd from the Eigen library:

typedef VectorXd Vec;

bool(*fn_pt)(Vec,Vec) = vecCompare;
set<Vec,bool(*)(Vec,Vec)> yx (fn_pt);

The function vecCompare ist defined as follows:

bool vecCompare(Vec v, Vec w) {
    int n = v.rows();

    for (int i = 0; i < n; ++i) {
        if (v(i) < w(i)) { 
            return true;
        } else if (v(i) > w(i)) {
            return false;
        }  
    }

   return false;
}

Unfortunality, I end up with duplicate elements in yx. Any ideas?

Edit1: For simple examples everything works fine, e.g.,

set<Vec,vecCompare> test;
Vec t(3);
t(0)=33;
t(1)=44;
t(2)=55;

test.insert(t);
test.insert(t);

I my code I insert about 2000 vectors and I get about 200 duplicate elements.

Edit2: The vectors are computed by an algorithm. I outputted the vectors in the order in which they are inserted into yx until two duplicate elements are inserted, resulting in the following list:

10068.4, 2355, 4794
9787.28, 4582, 2532
10188, 3218, 3111
7696.03, 3506, 3540
7933.94, 2864, 4844
8321.96, 4432, 2804
8502.21, 3732, 2928
9976.05, 3859, 2681
9623.74, 3397, 2967
8815.94, 2987, 3556
9082.79, 2693, 3954
9976.81, 2574, 3991
10002.5, 3443, 2915
8264.29, 3392, 3290
7169.08, 4594, 3622
7073.8, 4756, 3771
7005.82, 3749, 4985
7833, 4000, 3150
8096.63, 2876, 4193
8107.36, 2892, 4143
7459.51, 3246, 4489
9061.37, 2480, 4617
7718.64, 3001, 4820
9069.39, 2471, 4861
7744.1, 4449, 3155
8320.67, 4120, 2850
8875.47, 4655, 2596
8858.44, 4321, 2627
8616.2, 4085, 2759
8114.57, 3602, 3176
8114.57, 3602, 3176  

Then I created these 30 vectors by hand and inserted them by hand into a set. Suprisingly, everything worked fine. I don't understand this.

Edit3: I also noticed that when running the following, that zz stays at 0, although yx contains about 200 duplicates.

  int zz = 0;
  for (auto y1: yx) {
    int i = 0;
    for (auto y2: yx) {
      if (y1 == y2) {
        i++;
      }

      if (i > 1) zz++; 
    }
  }
1

There are 1 best solutions below

6
On BEST ANSWER

You could try to declare vecCompare as a functional object rather than a function.

typedef VectorXd Vec;
struct vecCompare {
    bool operator()(const Vec &v, const Vec &w) const
    {
        int n = v.rows();

        for (int i = 0; i < n; ++i) {
            if (v(i) < w(i)) { 
                return true;
            } else if (v(i) > w(i)) {
                return false;
            }  
        }

        return false;
    }
};

set<Vec, vecCompare> yx;

However, as long as VectorXd stores double as elements, you need to take special care of floating point precision issue. Two floating point numbers which seems to be equal may not be really equal.