{"id":23029643,"url":"https://github.com/antononcube/raku-math-sparsematrix","last_synced_at":"2025-04-02T20:25:35.076Z","repository":{"id":258977935,"uuid":"862064657","full_name":"antononcube/Raku-Math-SparseMatrix","owner":"antononcube","description":"Raku package for sparse matrix technology.","archived":false,"fork":false,"pushed_at":"2024-11-15T05:38:01.000Z","size":165,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-08T11:13:01.119Z","etag":null,"topics":["linear-algebra","raku","rakulang","sparse-matrix"],"latest_commit_sha":null,"homepage":"https://raku.land/zef:antononcube/Math::SparseMatrix","language":"Raku","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"artistic-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/antononcube.png","metadata":{"files":{"readme":"README-work.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-24T01:20:48.000Z","updated_at":"2025-01-02T06:47:38.000Z","dependencies_parsed_at":"2024-10-26T07:16:03.582Z","dependency_job_id":"b2ee58f5-d857-4f9e-90c3-dc27a3b5c92b","html_url":"https://github.com/antononcube/Raku-Math-SparseMatrix","commit_stats":null,"previous_names":["antononcube/raku-math-sparsematrix"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antononcube%2FRaku-Math-SparseMatrix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antononcube%2FRaku-Math-SparseMatrix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antononcube%2FRaku-Math-SparseMatrix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antononcube%2FRaku-Math-SparseMatrix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/antononcube","download_url":"https://codeload.github.com/antononcube/Raku-Math-SparseMatrix/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246886465,"owners_count":20849867,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linear-algebra","raku","rakulang","sparse-matrix"],"created_at":"2024-12-15T14:16:29.712Z","updated_at":"2025-04-02T20:25:35.044Z","avatar_url":"https://github.com/antononcube.png","language":"Raku","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Math::SparseMatrix\n\n\n[![Actions Status](https://github.com/antononcube/Raku-Math-SparseMatrix/actions/workflows/linux.yml/badge.svg)](https://github.com/antononcube/Raku-Math-SparseMatrix/actions)\n[![Actions Status](https://github.com/antononcube/Raku-Math-SparseMatrix/actions/workflows/macos.yml/badge.svg)](https://github.com/antononcube/Raku-Math-SparseMatrix/actions)\n[![Actions Status](https://github.com/antononcube/Raku-Math-SparseMatrix/actions/workflows/windows.yml/badge.svg)](https://github.com/antononcube/Raku-Math-SparseMatrix/actions)\n\n[![](https://raku.land/zef:antononcube/Math::SparseMatrix/badges/version)](https://raku.land/zef:antononcube/Math::SparseMatrix)\n[![License: Artistic-2.0](https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg)](https://opensource.org/licenses/Artistic-2.0)\n\n\nRaku package for sparse matrix algorithms:\n\n- Implements (some of) the algorithms described (and spelled-out in FORTRAN) in the book \n\"Sparse Matrix Technology\" by S. Pissanetzky, [SP1].\n\n- Provides convenient interface to accessing sparse matrix elements, rows, column, and sub-matrices. \n\n-----\n\n## Motivation\n\nSparse Matrix Algebra (SMA) is a \"must have\" for many computational workflows. \nHere is a (non-exhaustive) list given in the order of _my_ preferences:\n\n- Recommendation Systems (RS)\n    - I make recommenders often during Exploratory Data Analysis (EDA).\n    - For me, RS are \"first order regression.\"\n    - I also specialize in the making of RS.\n    - I implemented a Raku recommender without SMA, \n      [\"ML::StreamsBlendingRecommender\"](https://github.com/antononcube/Raku-ML-StreamsBlendingRecommender), [AAp1], \n      but it is too slow for \"serious\" datasets.\n      - Still useful; see [AAv1].\n- Latent Semantic Analysis (LSA)\n    - LSA is one my favorite Unsupervised Machine Learning (ML) workflows.\n    - That means that this SMA package should have algorithms facilitating the programming of:\n        - Singular Value Decomposition (SVD)\n        - Non-Negative Matrix Factorization (NNMF)\n- Graphs\n    - There is a natural (representation) connection between sparse matrices and graphs.\n    - Many graph algorithms can leverage (fast) SMA.\n    - So far (2024-09-25) the algorithms in \"Graph\", [AAp2], do not use SMA and that is feature- and speed limiting.\n- Optimization\n    - For large scale optimization problems using SMA is a must.\n        - Since their constraints are given with sparse matrices.\n- Partial Differential Equations (PDE) solving\n\n-----\n\n## Usage examples\n\nHere is a _simple_ sparse matrix in Compressed Sparse Row (CSR) format:\n\n```perl6\nuse Math::SparseMatrix;\nuse Math::SparseMatrix::Utilities;\n\nmy $nrow = 5;\nmy $ncol = 8;\nmy $density = 0.2;\nmy $tol = 0.01;\nmy $type = 'CSR';\n\nmy $matrix1 = generate-random-sparse-matrix($nrow, $ncol, :$density, :$tol, :$type):!decorated;\nsay $matrix1;\n```\n\nHere it is \"pretty printed\": \n\n```perl6\n$matrix1.print;\n```\n\nHere `10` is multiplied with all elements:\n\n```perl6\nmy $matrix2 = $matrix1.multiply(10); \n\n$matrix2.print;\n```\n\nHere is the dot-product of the original matrix with its transpose:\n\n```perl6\nmy $matrix3 = $matrix1.dot($matrix1.transpose); \n\n$matrix3.print;\n```\n\n-----\n\n## Special features\n\nHere are few features that other SMA packages typically do not provide.\n\n### Named rows and columns\n\nIt is very convenient to have named rows and columns that are respected (or preserved)\nin the typical SMA operations.\n\nHere is an example:\n\n```perl6\nmy $smat = Math::SparseMatrix.new($matrix1, row-names =\u003e 'a' .. 'e', column-names =\u003e 'A' .. 'H'); \n\n$smat.print;\n```\n\n\nHere is the dot-product of that matrix with its transpose:\n\n```perl6\nmy $smat2 = $smat.dot($smat.transpose); \n\n$smat2.round(0.02).print;\n```\n\n### Implicit value\n\nThe sparse matrices can have an _implicit value_ that is different from 0.\nFor example, adding a number to a sparse matrix produces another sparse matrix \nwith different implicit value:\n\n```perl6\nmy $matrix3 = $matrix1.add(10);\n```\n\n```perl6\n$matrix3.implicit-value\n```\n\nHere is the pretty print:\n\n```perl6\n$matrix3.print(:iv)\n```\n\n**Remark:** Currently, the implicit values are ignored in `dot`.\n\n-----\n\n## Design\n\n### General\n\n- There should be a \"main\" class, `Math::SpareMatrix` that:\n  - Provides the SMA functionalities\n  - Delegates to concrete sparse matrix classes that are based on different representation formats\n  - Can have named rows, columns, and dimensions\n  - Gives access to sparse matrix elements, rows, columns, and sub-matrices\n- The default or \"main\" core sparse matrix class should use Compressed Sparse Row (CSR) format.\n- Also, a class using Dictionary Of Keys (DOK) format should be provided.\n- The core sparse matrix classes do not have named rows, columns, and dimensions.\n- Ideally, a class using `NativeCall` should be implemented at some point.\n  - It looks like this is \"a must\", since the CSR and DOK classes are fairly slow.\n  - Both \"plain C\" and macOS [Accelerate](https://developer.apple.com/accelerate/) implementations should be made.\n- The _most important operation_ is Matrix-Vector Dot Product.\n  - The current design is to use one-row or one-column matrices for the vectors.\n  - Dense vectors are (of course) also supported\n\n### Object-Oriented Programming (OOP) architecture\n\n- The OOP [Decorator Design Pattern](https://en.wikipedia.org/wiki/Decorator_pattern) is used to organize the SMA functionalities.\n- In that pattern:\n  - The _Component_ is played by the class [`Math::SparseMatrix::Abstract`](./lib/Math/SparseMatrix/Abstract.rakumod).\n  - The _ConcreteComponent_ is played by the classes:\n    - [`Math::SparseMatrix::CSR`](./lib/Math/SparseMatrix/CSR.rakumod)\n    - [`Math::SparseMatrix::DOK`](./lib/Math/SparseMatrix/DOK.rakumod)\n  - The concrete component classes provide the core SMA operations.\n  - The _Decorator_ is played by [`Math::SparseMatrix`](./lib/Math/SparseMatrix.rakumod).\n    - That is a \"top level\", interface class.\n    - Allows access using named rows and columns.\n    - \"Hides\" the actual component class used.\n\nHere is a corresponding diagram:\n\n```mermaid\nclassDiagram\n    class Abstract[\"Math::SparseMatrix::Abstract\"] {\n        \u003c\u003cabstract\u003e\u003e\n        +value-at()\n        +row-at()\n        +column-at()\n        +row-slice()\n        +AT-POS()\n        +print()\n        +transpose()\n        +add()\n        +multiply()\n        +dot()\n    }\n\n    class CSRStruct {\n        \u003c\u003cC struct\u003e\u003e\n    }\n    \n    class NativeCSR[\"Math::SparseMatrix::CSR::Native\"] {\n        $row_ptr\n        $col_index\n        @values\n        nrow\n        ncol\n        implicit_value\n    }\n\n    class NativeAdapater[\"Math::SparseMatrix::NativeAdapter\"] {\n        +row-ptr\n        +col-index\n        +values\n        +nrow\n        +ncol\n        +implicit-value\n    }    \n\n    class CSR[\"Math::SparseMatrix::CSR\"] {\n        @row-ptr\n        @col-index\n        @values\n        nrow\n        ncol\n        implicit-value\n    }\n    \n    class DOK[\"Math::SparseMatrix::DOK\"] {\n        %adjacency-map\n        nrow\n        ncol\n        implicit-value\n    }\n    \n    class SparseMatrix[\"Math::SparseMatrix\"] {\n        Abstract core-matrix\n        +AT-POS()\n        +print()\n        +transpose()\n        +add()\n        +multiply()\n        +dot()\n    }\n    \n    CSR --\u003e Abstract : implements\n    DOK --\u003e Abstract : implements\n    NativeAdapater --\u003e Abstract : implements\n    SparseMatrix --\u003e Abstract : Hides actual component class\n    SparseMatrix *--\u003e Abstract\n    NativeAdapater *--\u003e NativeCSR\n    NativeCSR -- CSRStruct : reprents\n```\n\n### Implementation details\n\n- Again, the most important operation is Matrix-Vector Dot Product.\n    - It has to be as fast as possible.\n    - There are two Dot Product implementations for CSR:\n        - Direct\n        - Symbolic-\u0026-numeric\n    - (Currently) the direct one is 20-50% faster.\n- It seems it is a good idea to provide for some operations _symbolic_ (or sparse matrix elements pattern) methods.\n    - For example:\n        - `add-pattern` / `add`\n        - `dot-pattern` / `dot-numeric`\n- It is important to have access methods / operators.\n    - All three are used in the accessor implementation: `AT-POS`, `postcircumfix:\u003c[ ]\u003e`, `postcircumfix:\u003c[; ]\u003e` .\n\n\n-----\n\n## Performance\n\n- Performance of CSR and DOK sparse matrices is not good: between 40 to 150 times slower than Wolfram Language.\n  - (Using the same matrices, of course.)\n- It is somewhat surprising that DOK is faster than CSR. \n  - (Using pure-Raku.)\n- `NativeCall` based implementations are ≈ 100 times faster.\n  - See [\"Math::SparseMatrix::Native\"](https://github.com/antononcube/Raku-Math-SparseMatrix-Native), [AAp3].\n\n-----\n\n## Acknowledgements\n\nThanks to [@lizmat](https://github.com/lizmat) and [@tony-o](https://github.com/tony-o) for helping figuring out the proper use of `postcircumfix:\u003c[]\u003e` and `postcircumfix:\u003c[; ]\u003e`\nin order to have the named rows and columns functionalities.\n\n-----\n\n## References\n\n### Books\n\n[SP1] Sergio Pissanetzky, Sparse Matrix Technology, Academic Pr (January 1, 1984), ISBN-10: 0125575807, ISBN-13: 978-0125575805.\n\n### Packages\n\n[AAp1] Anton Antonov,\n[ML::StreamsBlendingRecommender Raku package](https://github.com/antononcube/Raku-ML-StreamsBlendingRecommender), \n(2021-2024),\n[GitHub/antononcube](https://github.com/antononcube).\n\n[AAp2] Anton Antonov,\n[Graph Raku package](https://github.com/antononcube/Raku-Graph),\n(2024),\n[GitHub/antononcube](https://github.com/antononcube).\n\n[AAp3] Anton Antonov,\n[Math::SparseMatrix::Native Raku package](https://github.com/antononcube/Raku-Math-SparseMatrix-Native),\n(2024),\n[GitHub/antononcube](https://github.com/antononcube).\n\n### Videos\n\n[AAv1] Anton Antonov,\n[\"TRC 2022 Implementation of ML algorithms in Raku\"](https://youtu.be/efRHfjYebs4?si=J5P8pK1TgGSxdlmD\u0026t=193),\n(2022),\n[YouTube/antononcube](https://www.youtube.com/@AAA4prediction).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantononcube%2Fraku-math-sparsematrix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fantononcube%2Fraku-math-sparsematrix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantononcube%2Fraku-math-sparsematrix/lists"}