failed assertion during applying BDCSVD

0

I am using the following struct in my project and the problem occurs in the second constructor. (I am using Visual Studio 2019.)

struct optimal_subspace {
    vector<Eigen::VectorXd> span;

    //empty constructor
    optimal_subspace() {}

    //constructor taking a pointset, the cluster number i and the size of subspaces q
    //used for the k-means subspace algorithm on the whole pointset
    optimal_subspace(vector<point>& pointset, int i, int q) {
        //declare a vector to contain the span
        vector<Eigen::VectorXd> subspace_span;
        //declare integers n,d to save the dimensions of the current data matrix
        int n, d;
        //declare integer r to save the minimum of n and d
        int r;
        //using the constructor of the struct subspacematrix to get the data matrix of cluster i, the cluster mean is already subtracted
        subspacematrix sm(pointset, i);
        Eigen::MatrixXd m = sm.matrix;
        //save the dimensions of m
        n = m.rows();
        d = m.cols();
        //determine min(n,d)
        r = min(n, d);
        //check if the cluster contains points
        if (sm.status == true) {
            //use either Jacobi or BDCSVD according to the size of m, declare v to save V from the SVD D = U E V^T or thin SVD
            //Jacobi better for matrices smaller than 16x16
            Eigen::MatrixXd v;
            //if r < q compute the Full decomposition as otherwise there are not enough singular vectors to obtain a q-dimensional subspace
            //else compute the thin decomposition
            clock_t start = clock();
            if (n < 16 & d < 16) {
                Eigen::JacobiSVD<Eigen::MatrixXd> svd(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
                v = svd.matrixV();
            }
            else {
                Eigen::BDCSVD<Eigen::MatrixXd> svd(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
                v = svd.matrixV();
            }
            clock_t stop = clock();
            svd_time += (double) (stop - start) / CLOCKS_PER_SEC;
            for (int j = 0; j < min(q, r); j++) {
                //V is of the form dxr, so, we take the r columns
                subspace_span.push_back(v.col(j));
                //currentsubspace.push_back(v.col(j) + mean);
            }
            //if r < q, we fill the subspaces by taking the coordinates of random points outside the cluster
            if (min(q, r) < q) {
                vector<int> non_cluster_indices = opp_ind(sm.cluster_indices, pointset.size());
                uniform_int_distribution<int> uniform_dist(0, non_cluster_indices.size());
                //pick randomly a point outside the cluster and add it
                for (int j = min(q, r); j < q; j++) {
                    Eigen::VectorXd non_cluster_vector = pointset[non_cluster_indices[uniform_dist(mt)]].getcoord();
                    subspace_span.push_back(non_cluster_vector);
                }
                //orthonormalize the span
                stableGramSchmidt(subspace_span, min(q, r));
            }
            if (subspace_span.size() == 0) cout << "error: empty subspace added" << endl;
        }
        span = subspace_span;
    }

    //constructor taking a pointset, the cluster number i and the size of subspaces q and a vector of indices representing a sample
    //used for sampling k-means
    optimal_subspace(vector<point>& pointset, int i, int q, vector<int> indices) {
        //declare a vector to contain the span
        vector<Eigen::VectorXd> subspace_span;
        //declare integers n,d to save the dimensions of the current data matrix
        int n, d;
        //declare integer r to save the minimum of n and d
        int r;
        //using the constructor of the struct subspacematrix to get the data matrix of cluster i, the cluster mean is already subtracted
        subspacematrix sm(pointset, indices, i);
        Eigen::MatrixXd m = sm.matrix;
        //save the dimensions of m
        n = m.rows();
        d = m.cols();
        //check if the cluster contains points
        if (sm.status == true) {
            //use either Jacobi or BDCSVD according to the size of m, declare v to save V from the SVD D = U E V^T or thin SVD
            //Jacobi better for matrices smaller than 16x16
            Eigen::MatrixXd v;
            //if r < q compute the Full decomposition as otherwise there are not enough singular vectors to obtain a q-dimensional subspace
            //else compute the thin decomposition
            clock_t start = clock();
            if (n < 16 & d < 16) {
                Eigen::JacobiSVD<Eigen::MatrixXd> svd(m, Eigen::ComputeThinU | Eigen::ComputeThinV);
                v = svd.matrixV();
            }
            else {
                //ofstream file("problematicmatrix.txt", ofstream::trunc);
                //file << sm.matrix.format(CommaInitFmt) << endl;
                //file.close();
                //Eigen::MatrixXd matrix = load_csv<Eigen::MatrixXd>("problematicmatrix.txt");

                Eigen::BDCSVD<Eigen::MatrixXd> svd(sm.matrix, Eigen::ComputeThinU | Eigen::ComputeThinV);
                v = svd.matrixV();
            }
            clock_t stop = clock();
            svd_time += (double) (stop - start) / CLOCKS_PER_SEC;
            int v_cols = v.cols();
            int fill_up_index = min(q, v_cols);
            for (int j = 0; j < fill_up_index; j++) {
                subspace_span.push_back(v.col(j));
            }
            //if we don't have enough columns, we fill the subspaces by taking the coordinates of random points outside the cluster
            if (fill_up_index < q) {
                vector<int> non_cluster_indices = opp_ind(sm.cluster_indices, indices);
                uniform_int_distribution<int> uniform_dist(0, non_cluster_indices.size() - 1);
                //pick randomly a point outside the cluster and add it
                for (int j = fill_up_index; j < q; j++) {
                    Eigen::VectorXd non_cluster_vector = pointset[non_cluster_indices[uniform_dist(mt)]].getcoord();
                    subspace_span.push_back(non_cluster_vector);
                }
                //orthonormalize the span
                stableGramSchmidt(subspace_span, fill_up_index);
            }
            if (subspace_span.size() == 0) cout << "error: empty subspace added" << endl;
        }
        span = subspace_span;
    }

};

I get the following exception:

Unhandled exception at 0x00007FF6CB72BD3B in MAaktuell.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.

and when debugging after getting it, I end up in the BDCSVD.h.

I also run it in debug mode and got the following error message:

Assertion failed: index >= 0 && index < size(), file C:\Users\Marcel\Desktop\eigen-3.3.7\eigen-3.3.7\Eigen\src\Core\DenseCoeffsBase.h, line 180

I stored the matrix using the I0 format provided by eigen in a txt.file as follows (and included it in the second constructor, it is commented right now):

                ofstream file("problematicmatrix.txt", ofstream::trunc);
                ile << sm.matrix.format(CommaInitFmt) << endl;
                file.close();

and uploaded it here:

problematic matrix in a txt.file

However, I tried to compute the BDCSVD for this matrix again as follows:

Eigen::MatrixXd matrix = load_csv<Eigen::MatrixXd>("problematicmatrix.txt");
Eigen::BDCSVD<Eigen::MatrixXd> svd(matrix, Eigen::ComputeThinU | Eigen::ComputeThinV);

and then, it works. If I include saving and loading the matrix in my method, it fails again. Can anyone help me finding the error? Why do I end up in the header of BDCSVD, when debugging?

c++
eigen
asked on Stack Overflow Nov 20, 2020 by MPB94

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0