Skylark (Sketching Library)  0.1
/var/lib/jenkins/jobs/Skylark/workspace/tests/unit/LocalSparseSketchApply.cpp
Go to the documentation of this file.
00001 
00013 #include <vector>
00014 
00015 #include <boost/mpi.hpp>
00016 #include <boost/test/minimal.hpp>
00017 
00018 #include "../../utility/distributions.hpp"
00019 #include "../../base/sparse_matrix.hpp"
00020 #include "../../sketch/sketch.hpp"
00021 
00022 
00023 template < typename InputMatrixType,
00024            typename OutputMatrixType = InputMatrixType >
00025 struct Dummy_t : public skylark::sketch::hash_transform_t<
00026     InputMatrixType, OutputMatrixType,
00027     boost::random::uniform_int_distribution,
00028     skylark::utility::rademacher_distribution_t > {
00029 
00030     typedef skylark::sketch::hash_transform_t<
00031         InputMatrixType, OutputMatrixType,
00032         boost::random::uniform_int_distribution,
00033         skylark::utility::rademacher_distribution_t >
00034             hash_t;
00035 
00036     Dummy_t(int N, int S, skylark::base::context_t& context)
00037         : skylark::sketch::hash_transform_t<InputMatrixType, OutputMatrixType,
00038           boost::random::uniform_int_distribution,
00039           skylark::utility::rademacher_distribution_t>(N, S, context)
00040     {}
00041 
00042     std::vector<size_t> getRowIdx() { return hash_t::row_idx; }
00043     std::vector<double> getRowValues() { return hash_t::row_value; }
00044 };
00045 
00046 int test_main(int argc, char *argv[]) {
00047 
00049     //[> Parameters <]
00050 
00051     //FIXME: use random sizes?
00052     const size_t n   = 10;
00053     const size_t m   = 5;
00054     const size_t n_s = 6;
00055     const size_t m_s = 3;
00056 
00057     typedef skylark::base::sparse_matrix_t<double> Matrix_t;
00058 
00060     //[> Setup test <]
00061 
00062     namespace mpi = boost::mpi;
00063     mpi::environment env(argc, argv);
00064     mpi::communicator world;
00065     const size_t rank = world.rank();
00066 
00067     skylark::base::context_t context (0);
00068 
00069     double count = 1.0;
00070 
00071     const int matrix_full = n * m;
00072     std::vector<int> colsf(m + 1);
00073     std::vector<int> rowsf(matrix_full);
00074     std::vector<double> valsf(matrix_full);
00075 
00076     for(size_t i = 0; i < m + 1; ++i)
00077         colsf[i] = i * n;
00078 
00079     for(size_t i = 0; i < matrix_full; ++i) {
00080         rowsf[i] = i % n;
00081         valsf[i] = count;
00082         count++;
00083     }
00084 
00085     Matrix_t A;
00086     A.attach(&colsf[0], &rowsf[0], &valsf[0], matrix_full, n, m, false);
00087 
00088     count = 1;
00089     const int* indptr = A.indptr();
00090     const int* indices = A.indices();
00091     const double* values = A.locked_values();
00092 
00093     for(int col = 0; col < A.width(); col++) {
00094         for(int idx = indptr[col]; idx < indptr[col + 1]; idx++) {
00095             BOOST_REQUIRE( values[idx] == count );
00096             count++;
00097         }
00098     }
00099 
00101     //[> Test COO to CSC <]
00102     typename Matrix_t::coords_t coords_mat;
00103     count = 1;
00104     for(int col = 0; col < A.width(); col++) {
00105         for(int row = 0; row < A.height(); row++) {
00106             typename Matrix_t::coord_tuple_t new_entry(row, col, count);
00107             coords_mat.push_back(new_entry);
00108             count++;
00109         }
00110     }
00111 
00112     Matrix_t A_coord;
00113     A_coord.set(coords_mat);
00114 
00115     count = 1;
00116     indptr = A_coord.indptr();
00117     indices = A_coord.indices();
00118     values = A_coord.locked_values();
00119 
00120     for(int col = 0; col < A_coord.width(); col++) {
00121         for(int idx = indptr[col]; idx < indptr[col + 1]; idx++) {
00122             BOOST_REQUIRE( values[idx] == count );
00123             count++;
00124         }
00125     }
00126 
00128     //[> Column wise application <]
00129 
00130     //[> 1. Create the sketching matrix <]
00131     Dummy_t<Matrix_t, Matrix_t> Sparse(n, n_s, context);
00132     std::vector<size_t> row_idx = Sparse.getRowIdx();
00133     std::vector<double> row_val = Sparse.getRowValues();
00134 
00135     // PI generated by random number gen
00136     int sketch_size = row_val.size();
00137     typename Matrix_t::coords_t coords;
00138     for(int i = 0; i < sketch_size; ++i) {
00139         typename Matrix_t::coord_tuple_t new_entry(row_idx[i], i, row_val[i]);
00140         coords.push_back(new_entry);
00141     }
00142 
00143     Matrix_t pi_sketch;
00144     pi_sketch.set(coords);
00145 
00146     //[> 2. Create sketched matrix <]
00147     Matrix_t sketch_A;
00148 
00149     //[> 3. Apply the transform <]
00150     Sparse.apply(A, sketch_A, skylark::sketch::columnwise_tag());
00151 
00152     BOOST_CHECK(sketch_A.height() == n_s);
00153     BOOST_CHECK(sketch_A.width()  == m);
00154 
00155     //[> 4. Build structure to compare: PI * A ?= sketch_A <]
00156     typename Matrix_t::coords_t coords_new;
00157     indptr = pi_sketch.indptr();
00158     indices = pi_sketch.indices();
00159     values = pi_sketch.locked_values();
00160 
00161     // multiply with vector where an entry has the value:
00162     //   col_idx * n + row_idx + 1.
00163     // See creation of A.
00164     for(int col = 0; col < pi_sketch.width(); col++) {
00165         for(int idx = indptr[col]; idx < indptr[col + 1]; idx++) {
00166             for(int ccol = 0; ccol < m; ++ccol) {
00167                 typename Matrix_t::coord_tuple_t new_entry(indices[idx], ccol,
00168                     values[idx] * (ccol * n + col + 1));
00169                 coords_new.push_back(new_entry);
00170             }
00171         }
00172     }
00173 
00174     Matrix_t expected_A;
00175     expected_A.set(coords_new, n_s, m);
00176 
00177     if (!static_cast<bool>(expected_A == sketch_A))
00178         BOOST_FAIL("Result of colwise application not as expected");
00179 
00180 
00182     //[> Row wise application <]
00183 
00184     //[> 1. Create the sketching matrix <]
00185     Dummy_t<Matrix_t, Matrix_t> Sparse_row(m, m_s, context);
00186     row_idx = Sparse_row.getRowIdx();
00187     row_val = Sparse_row.getRowValues();
00188 
00189     // PI generated by random number gen
00190     sketch_size = row_val.size();
00191     coords.clear();
00192     for(int i = 0; i < sketch_size; ++i) {
00193         typename Matrix_t::coord_tuple_t new_entry(i, row_idx[i], row_val[i]);
00194         coords.push_back(new_entry);
00195     }
00196 
00197     Matrix_t pi_sketch_row;
00198     pi_sketch_row.set(coords);
00199 
00200     //[> 2. Create sketched matrix <]
00201     Matrix_t sketch_A_row;
00202 
00203     //[> 3. Apply the transform <]
00204     Sparse_row.apply(A, sketch_A_row, skylark::sketch::rowwise_tag());
00205 
00206     BOOST_CHECK(sketch_A_row.height() == n);
00207     BOOST_CHECK(sketch_A_row.width()  == m_s);
00208 
00209     //[> 4. Build structure to compare: A * PI ?= sketch_A <]
00210     coords_new.clear();
00211     indptr = pi_sketch_row.indptr();
00212     indices = pi_sketch_row.indices();
00213     values = pi_sketch_row.locked_values();
00214 
00215     // multiply with vector where an entry has the value:
00216     //   col_idx * n + row_idx + 1.
00217     // See creation of A.
00218     for(int col = 0; col < pi_sketch_row.width(); col++) {
00219         for(int idx = indptr[col]; idx < indptr[col + 1]; idx++) {
00220             for(int row = 0; row < n; ++row) {
00221                 typename Matrix_t::coord_tuple_t new_entry(row, col,
00222                     values[idx] * (indices[idx] * n + row + 1));
00223                 coords_new.push_back(new_entry);
00224             }
00225         }
00226     }
00227 
00228     Matrix_t expected_A_row;
00229     expected_A_row.set(coords_new, n, m_s);
00230 
00231     if (!static_cast<bool>(expected_A_row == sketch_A_row))
00232         BOOST_FAIL("Result of rowwise application not as expected");
00233 
00234     return 0;
00235 }