Search code examples
c++boostublas

Why do I get a numeric::ublas::bad_index error when iterating on the elements of a sparse matrix?


I am using the Boost library, version 1.44.0 and c++ with gcc 4.0.

I have created a ublas::compressed_matrix<double> and I have filled it using the method insert_element(index1, index2, value). Thereafter I am iterating through the elements of the matrix and printing out the non-zero elements. I use the following code for iterating (note that i1_t and i2_t are typedef boost::numeric::ublas::compressed_matrix<double>::iterator):

   for (i1_t i1 = matrix->begin1(); i1 != matrix->end1(); i1++) {
    for (i2_t i2 = matrix->begin2(); i2 != matrix->end2(); i2++) {
     cout<<"("<<i2.index1()<<","<<i2.index2()<<")="<<*i2<<" ";
    }
    cout<<endl;
   }

Or alternatively the following:

    for (i1_t i1 = matrix->begin1(); i1 != matrix->end1(); i1++) {
    cout<<i1.index1()<<" -> ";
    for (i2_t i2 = matrix->begin2(); i2 != matrix->end2(); i2++) {
     cout<<i2.index2()<<" ("<<*i2<<") ";
    }
    cout<<endl;
   }

Of course, both of them are doing pretty much the same thing. The code follows the suggestions provided by another post in stackoverflow: iterating on non-zero elements

However, when running the code, I get that only the first few elements are correctly printed (in particular, this applies to the first six entries), until I get the following error:

Check failed in file /opt/local/include/boost/numeric/ublas/matrix_sparse.hpp at line 3109:
p
terminate called after throwing an instance of 'boost::numeric::ublas::bad_index'
  what():  bad index

All the elements, however, seem to be correctly inserted into the matrix. I am wondering what is going on, why I get this error and what does it mean?

Many thanks.


Solution

  • I have found what the problem was, and of course it was my mistake on the code.

    In fact the inner loop (i.e. the second for loop) iterates through the wrong thing. Originally I wrote:

    for (i2_t i2 = matrix->begin2(); i2 != matrix->end2(); i2++)
    

    However, i2 should not iterate from matrx->begin2() to matrix->end2(). Instead, the limits of the iteration for i2 should be i1.begin() and i1.end(), where i1 is the first iterator! Apologies for my mistake.

    So, to summarise, the correct loop should be:

    for (i1_t i1 = matrix->begin1(); i1 != matrix->end1(); i1++) {
       for (i2_t i2 = i1.begin(); i2 != i1.end(); i2++) {
          cout << "(" << i2.index1() << "," << i2.index2() << ")=" << *i2 << " ";
       }
       cout << endl;
    }