Skip to content

leannejdong/SparseTensor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NaĂŻve sparse matrix/tensor library

(Work in Progress)

Dependency

  • GCC10

  • GNU Build System (a.k.a. Make)

  • C++20

  • fast open-source formatting library {fmt}

(Doxygen was used to generate documentation, can be safely ignored)

Instruction

  • Copy codes below, save it in a file testlib.cpp in a directory parallel to the SparseTensor directory.

  • To build, use the following makefile

CXX=g++-10
CXXFLAGS=-std=c++2a -MD
sparse: testlib.o SparseTensor/src/SparseTensor.o
>-------$(CXX) -o $@ $^ -lfmt

clean:
>-------rm -f *.o sparse SparseTensor/src/*.o

-include *.d
-include SparseTensor/src/*.d

execute make from terminal to build. Use make clean to clean auxiliary files (if needed).

  • To run, execute ./sparse or ./sparse >file.txt 2>&1 to redirect all terminal output to a file. (Demo 1) Or ./sparse 2>&1 | tee file.txt to redirect all terminal output to a file (Demo 2)

Demo 1

#include"SparseTensor/include/matrix.h"
#include"SparseTensor/include/SparseTensor.h"
#include"SparseTensor/include/util.h"
#include"SparseTensor/include/Timer.h"
#include<random>
#include<fstream>
#include <iostream>
#include <vector>
using std::vector;
constexpr int M = 5;
constexpr int N = 5;
using SparseTensor::SparseMatrixEntry;
using SparseTensor::operator<<;
using SparseTensor::nested_print;
using SparseTensor::MatMultiply;
using SparseTensor::SparseMul;
using SparseTensor::KroneckersProduct;
using SparseTensor::KroneckersOuterProduct;
using SparseTensor::matrix;
using SparseTensor::Timer;
using SparseTensor::Matrix;
using SparseTensor::Tensor;
int main()
{
      std::cerr << "Convert dense data structure to sparse" << "\n";

    vector<vector<int>> a {{{0, 3, 0, 0, 0}, {22, 0, 0, 0, 17},
                                   {7, 5, 0, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 14, 0, 8}}};

    vector<SparseMatrixEntry> vs;
    vs.emplace_back(SparseMatrixEntry(0, 1, a[0][1]));
    vs.emplace_back(SparseMatrixEntry(1, 0, a[1][0]));
    vs.emplace_back(SparseMatrixEntry(1, 4, a[1][4]));
    vs.emplace_back(SparseMatrixEntry(2, 0, a[2][0]));
    vs.emplace_back(SparseMatrixEntry(2, 1, a[2][1]));
    vs.emplace_back(SparseMatrixEntry(2, 3, a[2][3]));
    vs.emplace_back(SparseMatrixEntry(4, 3, a[4][3]));
    vs.emplace_back(SparseMatrixEntry(4, 4, a[4][4]));
    std::cout << vs << "\n";
    std::cerr << "Convert sparse data structure to dense" << "\n";

    vector<SparseMatrixEntry> d;
    d.emplace_back(SparseMatrixEntry(0, 1, 3));
    d.emplace_back(SparseMatrixEntry(1, 0, 22));
    d.emplace_back(SparseMatrixEntry(1, 4, 17));
    d.emplace_back(SparseMatrixEntry(2, 0, 7));
    d.emplace_back(SparseMatrixEntry(2, 1, 5));
    d.emplace_back(SparseMatrixEntry(2, 3, 1));
    d.emplace_back(SparseMatrixEntry(4, 2, 14));
    d.emplace_back(SparseMatrixEntry(4, 4, 8));
    std::cout << d;
    std::cout << "\n";

    vector<std::vector<int>> vd(M, vector <int> (N, 0));
    vd[0][1] = d[0].value;
    vd[1][0] = d[1].value;
    vd[1][4] = d[2].value;
    vd[2][0] = d[3].value;
    vd[2][1] = d[4].value;
    vd[2][3] = d[5].value;
    vd[4][2] = d[6].value;
    vd[4][4] = d[7].value;
    std::cout << vd;

    std::cerr << "Perform matrix multiplication of 2D arrays: " << "\n";
    vector<vector<Value>> A {{{0, 3, 0, 0, 0}, {22, 0, 0, 0, 17},
                                     {7, 5, 0, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 14, 0, 8}}};

    vector<vector<Value>> B {{{0, 3, 0, 0, 0}, {0, 0, 0, 0, 17},
                                     {7, 5, 0, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 14, 0, 8}}};

    vector<vector<Value>> C = SparseMul(A, B);
    std::cout << C;
    
    Matrix D = MatMultiply(A, B);
    std::cout << D;

    std::cerr << "Compute kronecker products of 2 multidimensional arrays: " << "\n";
    Matrix m1{{1, 2}, {3, 4}, {1, 0}};
    Matrix m2{{0, 5, 2}, {6, 7, 3}};

    Matrix v(KroneckersProduct(m1, m2));
    std::cout << v;
    std::cerr << "Compute kronecker outer products of 2 multidimensional arrays: " << "\n";

    Tensor m(KroneckersOuterProduct(m1, m2));
    nested_print(std::span(m));

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(1.0, 10.0);
    vector<vector<double>> Matrix(5, vector<double>(7, 0));
    std::ofstream file("matrix.txt");
    for (auto &row : Matrix){
        for (auto &col : row){
            col = dis(gen);
            file << std::setw(4) << col;
        }
        file << '\n';
    }

    matrix mtx { { 1.0, 2.0 }, { 4.0, 5.0 }, { 8.0, 9.0 } } ;
    matrix mty { { 3.0, 2.0, 1.0 }, { 4.0, 2.0, 9.0 } } ;
    std::cerr << "Measure time taken for naive Matrix multiplication: " << "\n";
    Timer t;
    matrix mtz = mtx * mty;
    std::cerr << "Measure time taken for printing naive Matrix multiplication (fmt): " << "\n";
    Timer tt;
    for (int i=0; i!=mtz.num_rows(); ++i) {
        for (int j=0; j!=mtz.num_cols(); ++j) {
            std::cout << mtz(i,j) << " ";
        }
        std::cout << "\n";
    }
}
//g++-10 -std=c++2a -o sparse testlib.cpp SparseTensor/src/SparseTensor.cpp -lfmt

Demo 2 (Read user inputs)

#include"SparseTensor/include/matrix.h"
#include"SparseTensor/include/SparseTensor.h"
#include"SparseTensor/include/util.h"
#include"SparseTensor/include/Timer.h"
#include<random>
#include<iomanip>
#include<fstream>
#include <iostream>
#include <vector>
using std::cout;
using std::vector;
constexpr int M = 5;
constexpr int N = 5;
constexpr int K = 8;
using SparseTensor::SparseMatrixEntry;
using SparseTensor::operator<<;
using SparseTensor::nested_print;
using SparseTensor::MatMultiply;
using SparseTensor::SparseMul;
using SparseTensor::KroneckersProduct;
using SparseTensor::KroneckersOuterProduct;
using SparseTensor::matrix;
using SparseTensor::Timer;
using SparseTensor::Matrix;
using SparseTensor::Tensor;

void case1();
void case2();
void case3();
void case4();
void case5();
void case6();

int main()
{
    int choice;
    do
    {
        cout << "\n";
        cout << "Please choose an operation from the following: " << "\n";
        cout << "\n";
        cout << "\t 1. Convert dense data structure to sparse" << "\n";
        cout << "\t 2. Convert sparse data structure to dense" << "\n";
        cout << "\t 3. Perform matrix multiplication of 2D arrays: " << "\n";
        cout << "\t 4. Compute kronecker products of 2 multidimensional arrays: " << "\n";
        cout << "\t 5. Compute kronecker outer products of 2 multidimensional arrays: " << "\n";
        cout << "\t 6. Measure time taken for naive sparse Matrix multiplication: " << "\n";
        std::cin >> choice;

        switch (choice) {
            case 1:
                case1();
                break;
            case 2:
                case2();
                break;
            case 3:
                case3();
                break;
            case 4:
                case4();
                break;
            case 5:
                case5();
                break;
            case 6:
                case6();
                break;
            default:
                cout << " We're done " << "\n";
                return 0;
        }
    }
    while(choice != 0);
}

void case1()
{
    vector<vector<int>> a(M, vector<int>(N, 0));

    cout << "Please enter a 2D array: " << "\n";

    for (auto &row : a)
    {
        for (auto &col : row)
        {
            std::cin >> col;
        }
    }
    vector<SparseMatrixEntry> vs;
    vs.emplace_back(SparseMatrixEntry(0, 1, a[0][1]));
    vs.emplace_back(SparseMatrixEntry(1, 0, a[1][0]));
    vs.emplace_back(SparseMatrixEntry(1, 4, a[1][4]));
    vs.emplace_back(SparseMatrixEntry(2, 0, a[2][0]));
    vs.emplace_back(SparseMatrixEntry(2, 1, a[2][1]));
    vs.emplace_back(SparseMatrixEntry(2, 3, a[2][3]));
    vs.emplace_back(SparseMatrixEntry(4, 3, a[4][3]));
    vs.emplace_back(SparseMatrixEntry(4, 4, a[4][4]));
    std::cout << vs << "\n";
}
void case2()
{
    vector<SparseMatrixEntry> d;
    int i, j, k;

    for (int ii = 0; ii < 8; ++ii)
    {
        cout << "Please enter row position, column position and element value: ";
        std::cin >> i >> j >> k;
        d.emplace_back(SparseMatrixEntry(i, j, k));
    }
//    d.emplace_back(SparseMatrixEntry(0, 1, 3));
//    d.emplace_back(SparseMatrixEntry(1, 0, 22));
//    d.emplace_back(SparseMatrixEntry(1, 4, 17));
//    d.emplace_back(SparseMatrixEntry(2, 0, 7));
//    d.emplace_back(SparseMatrixEntry(2, 1, 5));
//    d.emplace_back(SparseMatrixEntry(2, 3, 1));
//    d.emplace_back(SparseMatrixEntry(4, 2, 14));
//    d.emplace_back(SparseMatrixEntry(4, 4, 8));
    std::cout << d;
    std::cout << "\n";

    std::vector<std::vector<int>> vd(M, std::vector<int>(N, 0));
    vd[0][1] = d[0].value;
    vd[1][0] = d[1].value;
    vd[1][4] = d[2].value;
    vd[2][0] = d[3].value;
    vd[2][1] = d[4].value;
    vd[2][3] = d[5].value;
    vd[4][2] = d[6].value;
    vd[4][4] = d[7].value;
    std::cout << vd;
}

void case3()
{
    vector<vector<int>> A(M, vector<int>(N, 0));
    vector<vector<int>> B(M, vector<int>(N, 0));

    cout << "Please enter a 2D array A: " << "\n";

    for (auto &row : A)
    {
        for (auto &col : row)
        {
            std::cin >> col;
        }
    }

    cout << "Please enter a 2D array B: " << "\n";

    for (auto &row : B)
    {
        for (auto &col : row)
        { 
            std::cin >> col;
        }
    }

//    vector<vector<Value>> A{{{0, 3, 0, 0, 0}, {22, 0, 0, 0, 17},
//                                    {7, 5, 0, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 14, 0, 8}}};
//
//    vector<vector<Value>> B{{{0, 3, 0, 0, 0}, {0, 0, 0, 0, 17},
//                                    {7, 5, 0, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 14, 0, 8}}};
    cout << "The multiplication result from SparMul() is: " << "\n";
    vector<vector<Value>> C = SparseMul(A, B);
    std::cout << C;
    cout << "The multiplication result from MatMultiply() is: " << "\n";
    Matrix D = MatMultiply(A, B);
    std::cout << D;

}
void case4()
{
    Matrix m1(M, vector<int>(N, 0));
    Matrix m2(M, vector<int>(N, 0));
    cout << "Please enter the first matrix for KroneckersProduct: " << "\n";
    for (auto &row : m1)
    {
        for (auto &col : row)
        { 
            std::cin >> col;
        }
    }
    cout << "Please enter the second matrix for KroneckersProduct: " << "\n";
    for (auto &row : m2)
    {
        for (auto &col : row)
        { 
            std::cin >> col;
        }
    }

    Matrix v(KroneckersProduct(m1, m2));
    std::cout << v;
}
void case5()
{
    Matrix m1(M, vector<int>(N, 0));
    Matrix m2(M, vector<int>(N, 0));
    cout << "Please enter the first matrix for KroneckersOuterProduct: " << "\n";
    for (auto &row : m1)
    {
        for (auto &col : row)
        {
            std::cin >> col;
        }
    }
    cout << "Please enter the second matrix for KroneckersOuterProduct: " << "\n";
    for (auto &row : m2)
    {
        for (auto &col : row))
        {
            std::cin >> col;
        }
    }
    
    Tensor m(KroneckersOuterProduct(m1, m2));
    nested_print(std::span(m));

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(1.0, 10.0);
    vector<vector<double>> Matrix(5, vector<double>(7, 0));
    std::ofstream file("matrix.txt");
    for (auto &row : Matrix) {
        for (auto &col : row) {
            col = dis(gen);
            file << std::setw(4) << col;
        }
        file << '\n';
    }
}
void case6()
{
    matrix<int, double> mtx(M, N, 0);
    matrix<int, double> mty(M, N, 0);

    cout << "Please enter element of sparse matrix A" << "\n";
    for (int i = 0; i != mtx.num_rows(); ++i) {
        for (int j = 0; j != mtx.num_cols(); ++j) {
            std::cin >> mtx(i, j) ;
        }
    }
    cout << "Please enter element of sparse matrix B" << "\n";
    for (int i = 0; i != mty.num_rows(); ++i) {
        for (int j = 0; j != mty.num_cols(); ++j) {
            std::cin >> mty(i, j) ;
        }
    }
    Timer t;
    matrix<int, double> mtz = mtx * mty;
    std::cerr << "Measure time taken for printing naive Matrix multiplication (fmt): " << "\n";
    Timer tt;
    for (int i = 0; i != mtz.num_rows(); ++i) {
        for (int j = 0; j != mtz.num_cols(); ++j) {
            std::cout << mtz(i, j) << " ";
        }
        std::cout << "\n";
    }
}



//g++-10 -std=c++2a -o sparse testlib.cpp SparseTensor/src/SparseTensor.cpp -lfmt

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published