int test_main(int argc, char *argv[]) {

    //////////////////////////////////////////////////////////////////////////
    //[> Parameters <]

    //FIXME: use random sizes?
    const size_t n   = 10;
    const size_t m   = 5;
    const size_t n_s = 6;
    const size_t m_s = 3;

    typedef skylark::base::sparse_matrix_t<double> Matrix_t;

    //////////////////////////////////////////////////////////////////////////
    //[> Setup test <]

    namespace mpi = boost::mpi;
    mpi::environment env(argc, argv);
    mpi::communicator world;
    const size_t rank = world.rank();

    skylark::base::context_t context (0);

    double count = 1.0;

    const int matrix_full = n * m;
    std::vector<int> colsf(m + 1);
    std::vector<int> rowsf(matrix_full);
    std::vector<double> valsf(matrix_full);

    for(size_t i = 0; i < m + 1; ++i)
        colsf[i] = i * n;

    for(size_t i = 0; i < matrix_full; ++i) {
        rowsf[i] = i % n;
        valsf[i] = count;
        count++;
    }

    Matrix_t A;
    A.attach(&colsf[0], &rowsf[0], &valsf[0], matrix_full, n, m, false);

    count = 1;
    const int* indptr = A.indptr();
    const int* indices = A.indices();
    const double* values = A.locked_values();

    for(int col = 0; col < A.width(); col++) {
        for(int idx = indptr[col]; idx < indptr[col + 1]; idx++) {
            BOOST_REQUIRE( values[idx] == count );
            count++;
        }
    }

    //////////////////////////////////////////////////////////////////////////
    //[> Test COO to CSC <]
    typename Matrix_t::coords_t coords_mat;
    count = 1;
    for(int col = 0; col < A.width(); col++) {
        for(int row = 0; row < A.height(); row++) {
            typename Matrix_t::coord_tuple_t new_entry(row, col, count);
            coords_mat.push_back(new_entry);
            count++;
        }
    }

    Matrix_t A_coord;
    A_coord.set(coords_mat);

    count = 1;
    indptr = A_coord.indptr();
    indices = A_coord.indices();
    values = A_coord.locked_values();

    for(int col = 0; col < A_coord.width(); col++) {
        for(int idx = indptr[col]; idx < indptr[col + 1]; idx++) {
            BOOST_REQUIRE( values[idx] == count );
            count++;
        }
    }

    //////////////////////////////////////////////////////////////////////////
    //[> Column wise application <]

    //[> 1. Create the sketching matrix <]
    Dummy_t<Matrix_t, Matrix_t> Sparse(n, n_s, context);
    std::vector<size_t> row_idx = Sparse.getRowIdx();
    std::vector<double> row_val = Sparse.getRowValues();

    // PI generated by random number gen
    int sketch_size = row_val.size();
    typename Matrix_t::coords_t coords;
    for(int i = 0; i < sketch_size; ++i) {
        typename Matrix_t::coord_tuple_t new_entry(row_idx[i], i, row_val[i]);
        coords.push_back(new_entry);
    }

    Matrix_t pi_sketch;
    pi_sketch.set(coords);

    //[> 2. Create sketched matrix <]
    Matrix_t sketch_A;

    //[> 3. Apply the transform <]
    Sparse.apply(A, sketch_A, skylark::sketch::columnwise_tag());

    BOOST_CHECK(sketch_A.height() == n_s);
    BOOST_CHECK(sketch_A.width()  == m);

    //[> 4. Build structure to compare: PI * A ?= sketch_A <]
    typename Matrix_t::coords_t coords_new;
    indptr = pi_sketch.indptr();
    indices = pi_sketch.indices();
    values = pi_sketch.locked_values();

    // multiply with vector where an entry has the value:
    //   col_idx * n + row_idx + 1.
    // See creation of A.
    for(int col = 0; col < pi_sketch.width(); col++) {
        for(int idx = indptr[col]; idx < indptr[col + 1]; idx++) {
            for(int ccol = 0; ccol < m; ++ccol) {
                typename Matrix_t::coord_tuple_t new_entry(indices[idx], ccol,
                    values[idx] * (ccol * n + col + 1));
                coords_new.push_back(new_entry);
            }
        }
    }

    Matrix_t expected_A;
    expected_A.set(coords_new, n_s, m);

    if (!static_cast<bool>(expected_A == sketch_A))
        BOOST_FAIL("Result of colwise application not as expected");


    //////////////////////////////////////////////////////////////////////////
    //[> Row wise application <]

    //[> 1. Create the sketching matrix <]
    Dummy_t<Matrix_t, Matrix_t> Sparse_row(m, m_s, context);
    row_idx = Sparse_row.getRowIdx();
    row_val = Sparse_row.getRowValues();

    // PI generated by random number gen
    sketch_size = row_val.size();
    coords.clear();
    for(int i = 0; i < sketch_size; ++i) {
        typename Matrix_t::coord_tuple_t new_entry(i, row_idx[i], row_val[i]);
        coords.push_back(new_entry);
    }

    Matrix_t pi_sketch_row;
    pi_sketch_row.set(coords);

    //[> 2. Create sketched matrix <]
    Matrix_t sketch_A_row;

    //[> 3. Apply the transform <]
    Sparse_row.apply(A, sketch_A_row, skylark::sketch::rowwise_tag());

    BOOST_CHECK(sketch_A_row.height() == n);
    BOOST_CHECK(sketch_A_row.width()  == m_s);

    //[> 4. Build structure to compare: A * PI ?= sketch_A <]
    coords_new.clear();
    indptr = pi_sketch_row.indptr();
    indices = pi_sketch_row.indices();
    values = pi_sketch_row.locked_values();

    // multiply with vector where an entry has the value:
    //   col_idx * n + row_idx + 1.
    // See creation of A.
    for(int col = 0; col < pi_sketch_row.width(); col++) {
        for(int idx = indptr[col]; idx < indptr[col + 1]; idx++) {
            for(int row = 0; row < n; ++row) {
                typename Matrix_t::coord_tuple_t new_entry(row, col,
                    values[idx] * (indices[idx] * n + row + 1));
                coords_new.push_back(new_entry);
            }
        }
    }

    Matrix_t expected_A_row;
    expected_A_row.set(coords_new, n, m_s);

    if (!static_cast<bool>(expected_A_row == sketch_A_row))
        BOOST_FAIL("Result of rowwise application not as expected");

    return 0;
}
int test_main(int argc, char *argv[]) {

    //////////////////////////////////////////////////////////////////////////
    //[> Parameters <]

    //FIXME: use random sizes?
    const size_t n   = 100;
    const size_t m   = 50;
    const size_t n_s = 60;
    const size_t m_s = 30;

    //////////////////////////////////////////////////////////////////////////
    //[> Setup test <]
    namespace mpi = boost::mpi;

    El::Initialize(argc, argv);

    mpi::environment env(argc, argv);
    mpi::communicator world;

    MPI_Comm mpi_world(world);
    El::Grid grid(mpi_world);

    const size_t rank = world.rank();

    skylark::base::context_t context (0);

    double count = 1.0;

    const size_t matrix_full = n * m;
    mpi_vector_t colsf(matrix_full);
    mpi_vector_t rowsf(matrix_full);
    mpi_vector_t valsf(matrix_full);

    for(size_t i = 0; i < matrix_full; ++i) {
        colsf.SetElement(i, i % m);
        rowsf.SetElement(i, i / m);
        valsf.SetElement(i, count);
        count++;
    }

    DistMatrixType A(n, m, rowsf, colsf, valsf);
    mpi_vector_t zero;

    count = 1.0;
    El::Matrix<double> local_A(n, m);
    for( size_t j = 0; j < local_A.Height(); j++ )
        for( size_t i = 0; i < local_A.Width(); i++ )
            local_A.Set(j, i, count++);


    El::DistMatrix<double, El::STAR, El::STAR> result(grid);

    // columnwise application
    DistMatrixType expected_A;
    DistMatrixType pi_sketch(n_s, n, zero, zero, zero);

    // rowwise application
    DistMatrixType expected_AR;
    DistMatrixType pi_sketch_r(m_s, m, zero, zero, zero);

    //////////////////////////////////////////////////////////////////////////
    //[> Column wise application DistSparseMatrix -> DistMatrix[MC/MR] <]

    typedef El::DistMatrix<double> mcmr_target_t;

    //[> 1. Create the sketching matrix <]
    Dummy_t<DistMatrixType, mcmr_target_t> Sparse(n, n_s, context);

    //[> 2. Create space for the sketched matrix <]
    mcmr_target_t sketch_A(n_s, m, grid);
    El::Zero(sketch_A);

    //[> 3. Apply the transform <]
    Sparse.apply(A, sketch_A, skylark::sketch::columnwise_tag());

    //[> 4. Build structure to compare <]
    // easier to check if all processors own result
    result = sketch_A;

    compute_sketch_matrix(Sparse, A, pi_sketch);
    expected_A = Mult_AnXBn_Synch<PTDD, double, col_t>(
            pi_sketch, A, false, false);

    compare_result(rank, expected_A, result);

    //////////////////////////////////////////////////////////////////////////
    //[> Column wise application DistSparseMatrix -> DistMatrix[VC/*] <]

    typedef El::DistMatrix<double, El::VC, El::STAR> vcs_target_t;

    //[> 1. Create the sketching matrix <]
    Dummy_t<DistMatrixType, vcs_target_t> SparseVC(n, n_s, context);

    //[> 2. Create space for the sketched matrix <]
    vcs_target_t sketch_A_vcs(n_s, m, grid);
    El::Zero(sketch_A_vcs);

    //[> 3. Apply the transform <]
    SparseVC.apply(A, sketch_A_vcs, skylark::sketch::columnwise_tag());

    //[> 4. Build structure to compare <]
    // easier to check if all processors own result
    result = sketch_A_vcs;

    compute_sketch_matrix(SparseVC, A, pi_sketch);
    expected_A = Mult_AnXBn_Synch<PTDD, double, col_t>(
            pi_sketch, A, false, false);

    compare_result(rank, expected_A, result);

    //////////////////////////////////////////////////////////////////////////
    //[> Column wise application DistSparseMatrix -> DistMatrix[*/VR] <]

    typedef El::DistMatrix<double, El::STAR, El::VR> svr_target_t;

    //[> 1. Create the sketching matrix <]
    Dummy_t<DistMatrixType, svr_target_t> SparseVR(n, n_s, context);

    //[> 2. Create space for the sketched matrix <]
    svr_target_t sketch_A_svr(n_s, m, grid);
    El::Zero(sketch_A_svr);

    //[> 3. Apply the transform <]
    SparseVR.apply(A, sketch_A_svr, skylark::sketch::columnwise_tag());

    //[> 4. Build structure to compare <]
    // easier to check if all processors own result
    result = sketch_A_svr;

    compute_sketch_matrix(SparseVR, A, pi_sketch);
    expected_A = Mult_AnXBn_Synch<PTDD, double, col_t>(
            pi_sketch, A, false, false);

    compare_result(rank, expected_A, result);

    //////////////////////////////////////////////////////////////////////////
    //[> Column wise application DistSparseMatrix -> DistMatrix[*/*] <]

    typedef El::DistMatrix<double, El::STAR, El::STAR> st_target_t;

    //[> 1. Create the sketching matrix <]
    Dummy_t<DistMatrixType, st_target_t> SparseST(n, n_s, context);

    //[> 2. Create space for the sketched matrix <]
    st_target_t sketch_A_st(n_s, m, grid);
    El::Zero(sketch_A_st);

    //[> 3. Apply the transform <]
    SparseST.apply(A, sketch_A_st, skylark::sketch::columnwise_tag());

    //[> 4. Compare <]
    compute_sketch_matrix(SparseST, A, pi_sketch);
    expected_A = Mult_AnXBn_Synch<PTDD, double, col_t>(
            pi_sketch, A, false, false);

    compare_result(rank, expected_A, sketch_A_st);

    //////////////////////////////////////////////////////////////////////////
    //[> Column wise application DistSparseMatrix -> LocalDenseMatrix <]

    Dummy_t<DistMatrixType, El::Matrix<double>> LocalSparse(n, n_s, context);
    El::Matrix<double> local_sketch_A(n_s, m);
    El::Zero(local_sketch_A);
    LocalSparse.apply(A, local_sketch_A, skylark::sketch::columnwise_tag());

    El::Matrix<double> pi_sketch_l(n_s, n);
    El::Zero(pi_sketch_l);
    El::Matrix<double> expected_A_l(n_s, m);
    El::Zero(expected_A_l);

    if(rank == 0) {
        // PI generated by random number gen
        std::vector<size_t> row_idx = LocalSparse.getRowIdx();
        std::vector<double> row_val = LocalSparse.getRowValues();

        int sketch_size = row_val.size();
        typename LocalMatrixType::coords_t coords;

        for(int i = 0; i < sketch_size; ++i)
            pi_sketch_l.Set(row_idx[i], i, row_val[i]);

        El::Gemm(El::NORMAL, El::NORMAL, 1.0, pi_sketch_l, local_A,
                   0.0, expected_A_l);

        for(int col = 0; col < expected_A_l.Width(); col++) {
            for(int row = 0; row < expected_A_l.Height(); row++) {
                if(local_sketch_A.Get(row, col) !=
                        expected_A_l.Get(row, col))
                    BOOST_FAIL("Result of local colwise application not as expected");
            }
        }
    }


    //////////////////////////////////////////////////////////////////////////
    //[> Row wise application DistSparseMatrix -> DistMatrix[MC/MR] <]

    //[> 1. Create the sketching matrix <]
    Dummy_t<DistMatrixType, mcmr_target_t> Sparse_r(m, m_s, context);

    //[> 2. Create space for the sketched matrix <]
    mcmr_target_t sketch_A_r(n, m_s, grid);
    El::Zero(sketch_A_r);

    //[> 3. Apply the transform <]
    Sparse_r.apply(A, sketch_A_r, skylark::sketch::rowwise_tag());

    //[> 4. Build structure to compare <]
    // easier to check if all processors own result
    result = sketch_A_r;

    compute_sketch_matrix(Sparse_r, A, pi_sketch_r);
    pi_sketch_r.Transpose();
    expected_AR = Mult_AnXBn_Synch<PTDD, double, col_t>(
            A, pi_sketch_r, false, false);

    compare_result(rank, expected_AR, result);

    //////////////////////////////////////////////////////////////////////////
    //[> Row wise application DistSparseMatrix -> DistMatrix[VC/*] <]

    //[> 1. Create the sketching matrix <]
    Dummy_t<DistMatrixType, vcs_target_t> Sparse_r_vcs(m, m_s, context);

    //[> 2. Create space for the sketched matrix <]
    vcs_target_t sketch_A_r_vcs(n, m_s, grid);
    El::Zero(sketch_A_r_vcs);

    //[> 3. Apply the transform <]
    Sparse_r_vcs.apply(A, sketch_A_r_vcs, skylark::sketch::rowwise_tag());

    //[> 4. Build structure to compare <]
    // easier to check if all processors own result
    result = sketch_A_r_vcs;

    pi_sketch_r.Transpose();
    compute_sketch_matrix(Sparse_r_vcs, A, pi_sketch_r);
    pi_sketch_r.Transpose();
    expected_AR = Mult_AnXBn_Synch<PTDD, double, col_t>(
            A, pi_sketch_r, false, false);

    compare_result(rank, expected_AR, result);

    //////////////////////////////////////////////////////////////////////////
    //[> Row wise application DistSparseMatrix -> LocalDenseMatrix <]

    Dummy_t<DistMatrixType, El::Matrix<double>> LocalSparse_r(m, m_s, context);
    El::Matrix<double> local_sketch_A_r(n, m_s);
    El::Zero(local_sketch_A_r);
    LocalSparse_r.apply(A, local_sketch_A_r, skylark::sketch::rowwise_tag());

    El::Matrix<double> local_pi_sketch_r(m_s, m);
    El::Zero(local_pi_sketch_r);
    El::Matrix<double> expected_A_r(n, m_s);
    El::Zero(expected_A_r);

    if(rank == 0) {
        // PI generated by random number gen
        std::vector<size_t> row_idx = LocalSparse_r.getRowIdx();
        std::vector<double> row_val = LocalSparse_r.getRowValues();

        int sketch_size = row_val.size();
        typename LocalMatrixType::coords_t coords;

        for(int i = 0; i < sketch_size; ++i)
            local_pi_sketch_r.Set(row_idx[i], i, row_val[i]);

        El::Gemm(El::NORMAL, El::TRANSPOSE, 1.0, local_A, local_pi_sketch_r,
                   0.0, expected_A_r);

        for(int col = 0; col < expected_A_r.Width(); col++) {
            for(int row = 0; row < expected_A_r.Height(); row++) {
                if(local_sketch_A_r.Get(row, col) !=
                        expected_A_r.Get(row, col))
                    BOOST_FAIL("Result of local rowwise application not as expected");
            }
        }
    }

    return 0;
}
Example #3
0
int test_main(int argc, char *argv[]) {

    //////////////////////////////////////////////////////////////////////////
    //[> Parameters <]
    const size_t n   = 10;
    const size_t m   = 5;
    const size_t n_s = 6;
    const size_t m_s = 3;

    const int seed = static_cast<int>(rand() * 100);

    typedef FullyDistVec<size_t, double> mpi_vector_t;
    typedef SpDCCols<size_t, double> col_t;
    typedef SpParMat<size_t, double, col_t> DistMatrixType;

    namespace mpi = boost::mpi;
    mpi::environment env(argc, argv);
    mpi::communicator world;
    const size_t rank = world.rank();
    skylark::base::context_t context (seed);

    double count = 1.0;

    const size_t matrix_full = n * m;
    mpi_vector_t colsf(matrix_full);
    mpi_vector_t rowsf(matrix_full);
    mpi_vector_t valsf(matrix_full);

    for(size_t i = 0; i < matrix_full; ++i) {
        colsf.SetElement(i, i % m);
        rowsf.SetElement(i, i / m);
        valsf.SetElement(i, count);
        count++;
    }

    DistMatrixType A(n, m, rowsf, colsf, valsf);

    //////////////////////////////////////////////////////////////////////////
    //[> Setup test <]

    //[> 1. Create the sketching matrix and dump JSON <]
    skylark::sketch::CWT_t<DistMatrixType, DistMatrixType>
    Sparse(n, n_s, context);

    // dump to property tree
    boost::property_tree::ptree pt = Sparse.get_data()->to_ptree();

    //[> 2. Dump the JSON string to file <]
    std::ofstream out("sketch.json");
    write_json(out, pt);
    out.close();

    //[> 3. Create a sketch from the JSON file. <]
    std::ifstream file;
    std::stringstream json;
    file.open("sketch.json", std::ios::in);

    boost::property_tree::ptree json_tree;
    boost::property_tree::read_json(file, json_tree);

    skylark::sketch::CWT_t<DistMatrixType, DistMatrixType> tmp(json_tree);

    //[> 4. Both sketches should compute the same result. <]
    mpi_vector_t zero;
    DistMatrixType sketch_A(n_s, m, zero, zero, zero);
    DistMatrixType sketch_Atmp(n_s, m, zero, zero, zero);

    Sparse.apply(A, sketch_A, skylark::sketch::columnwise_tag());
    tmp.apply(A, sketch_Atmp, skylark::sketch::columnwise_tag());

    if (!static_cast<bool>(sketch_A == sketch_Atmp))
        BOOST_FAIL("Applied sketch did not result in same result");

    return 0;
}