{"id":20848174,"url":"https://github.com/tlcfem/vpmr","last_synced_at":"2025-05-12T02:32:24.914Z","repository":{"id":147152355,"uuid":"616652418","full_name":"TLCFEM/vpmr","owner":"TLCFEM","description":"C++/Python implementation of the VPMR algorithm","archived":false,"fork":false,"pushed_at":"2023-12-19T14:25:02.000Z","size":469,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2023-12-20T12:47:07.983Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://doi.org/10.1007/s10915-022-01999-1","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TLCFEM.png","metadata":{"files":{"readme":"README.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}},"created_at":"2023-03-20T20:09:36.000Z","updated_at":"2024-01-21T02:24:36.288Z","dependencies_parsed_at":"2023-12-19T05:08:11.485Z","dependency_job_id":"d5f7f41d-187d-4984-9167-6f6f61d4d6c9","html_url":"https://github.com/TLCFEM/vpmr","commit_stats":null,"previous_names":[],"tags_count":4,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TLCFEM%2Fvpmr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TLCFEM%2Fvpmr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TLCFEM%2Fvpmr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TLCFEM%2Fvpmr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TLCFEM","download_url":"https://codeload.github.com/TLCFEM/vpmr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225116087,"owners_count":17423176,"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":[],"created_at":"2024-11-18T02:24:56.470Z","updated_at":"2025-05-12T02:32:24.902Z","avatar_url":"https://github.com/TLCFEM.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# VPMR C++ Implementation\n\n\u003cimg src=\"resource/vpmr.svg\" width=\"150\" align=\"middle\"/\u003e\n\n[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7770193.svg)](https://doi.org/10.5281/zenodo.7770193)\n[![codecov](https://codecov.io/gh/TLCFEM/vpmr/branch/master/graph/badge.svg?token=9QE6SQC3ZG)](https://codecov.io/gh/TLCFEM/vpmr)\n[![PyPI version](https://badge.fury.io/py/pyvpmr.svg)](https://pypi.org/project/pyvpmr/)\n[![Docker](https://img.shields.io/docker/image-size/tlcfem/vpmr)](https://hub.docker.com/r/tlcfem/vpmr/tags)\n\n[![gplv3-or-later](https://www.gnu.org/graphics/gplv3-or-later.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html)\n\n## Call For Help\n\n- [ ] **more performant parallel SVD algorithm**: `eigen` only provides sequential SVD\n- [ ] **alternative integration**: currently only Gauss-Legendre quadrature is available\n\n## What Is This?\n\nThis is a C++ implementation of the VPMR algorithm to compute the approximation of arbitrary smooth kernel.\nA Python package is also provided.\n\nCheck the reference paper [10.1007/s10915-022-01999-1](https://doi.org/10.1007/s10915-022-01999-1) and\nthe [original](https://github.com/ZXGao97/VPMR) MATLAB implementation for more details.\n\nIn short, the algorithm tries to find a summation of exponentials to approximate a given kernel function.\nIn mathematical terms, it looks for a set of $m_j$ and $s_j$ such that\n\n$$\n\\max_{t\\in{}I}\\left\\|g(t)-\\sum_jm_j\\exp(-s_jt)\\right\\|\u003c\\epsilon.\n$$\n\nIn the above, $g(t)$ is the given kernel function and $\\epsilon$ is the prescribed tolerance.\n\n## Dependency\n\nThe following libraries are required:\n\n1. [gmp](https://gmplib.org/) for multiple precision arithmetic\n2. [mpfr](https://www.mpfr.org/) for multiple-precision floating-point computations\n3. [tbb](https://github.com/oneapi-src/oneTBB) for parallel computing\n\nThe following libraries are included:\n\n1. [mpreal](http://www.holoborodko.com/pavel/mpfr/) `mpreal` type C++ wrapper, included\n2. [Eigen](https://eigen.tuxfamily.org/) for matrix decomposition, included\n3. [exprtk](https://github.com/ArashPartow/exprtk.git) for expression parsing, included\n4. [exprtk-custom-types](https://github.com/ArashPartow/exprtk-custom-types.git) for `mpreal` support, included\n\n## How To\n\n### Python Package\n\n\u003e [!WARNING]\n\u003e The Python module needs external libraries to be installed.\n\n\u003e [!WARNING]\n\u003e Windows users need to have a working [MSYS2](https://www.msys2.org/) environment. See below for more details.\n\u003e For other environments, you need to figure out how to install `gmp` and `mpfr` on your own.\n\nOn RPM-based Linux distributions (using `dnf`), if you are:\n\n1. compiling the application from source (or wheels are not\n   available), `sudo dnf install -y gcc-c++ tbb-devel mpfr-devel gmp-devel`\n2. using the packaged binary (wheels are available), `sudo dnf install -y gmp mpfr tbb`\n\nOn DEB-based Linux distributions (using `apt`), you need to `sudo apt install -y g++ libtbb-dev libmpfr-dev libgmp-dev`.\n\nOn macOS, you need to `brew install tbb mpfr gmp`.\n\nThen install the package with `pip`.\n\n```bash\npip install pyvpmr\n```\n\nIf the corresponding wheel is not available, the package will be compiled, which takes a few minutes.\nThe execution of the algorithm always requires available `gmp`, `mpfr` and `tbb` libraries.\n\n#### Jumpstart\n\n```python\nimport numpy as np\n\nfrom pyvpmr import vpmr, plot\n\n\ndef kernel(x):\n    return np.exp(-x ** 2 / 4)\n\n\nif __name__ == '__main__':\n    m, s = vpmr(n=50, k='exp(-t^2/4)')\n    plot(m, s, kernel)\n```\n\n### Usage\n\nAll available options are:\n\n```text\nUsage: vpmr [options]\n\nOptions:\n\n    -n, --max-terms             \u003cint\u003e     number of terms (default: 10)\n    -c, --max-exponent          \u003cint\u003e     maximum exponent (default: 4)\n    -d, --precision-bits        \u003cint\u003e     number of precision bits (default: 512)\n    -q, --quadrature-order      \u003cint\u003e     quadrature order (default: 500)\n    -m, --precision-multiplier  \u003cfloat\u003e   precision multiplier (default: 1.5)\n    -e, --tolerance             \u003cfloat\u003e   tolerance (default: 1E-8)\n    -k, --kernel                \u003cstring\u003e  file name of kernel function (default uses: exp(-t^2/4))\n    -s, --singular-values                 print singular values\n    -w, --weights                         print weights\n    -h, --help                            print this help message\n```\n\nThe minimum required precision can be estimated by the parameter $n$.\nThe algorithm involves the computation of $C(4n,k)$ and $2^{4n}$.\nThe number of precision bits shall be at least $4n+\\log_2C(4n,2n)$.\nIn the implementation, this number will be further multiplied by the parameter $m$.\n\n#### Example\n\nThe default kernel is `exp(-t^2/4)`. One can run the application with the following command:\n\n```bash\n./vpmr -n 30\n```\n\nThe output is:\n\n```text\nUsing the following parameters:\n       terms = 30.\n    exponent = 4.\n   precision = 355.\n quad. order = 500.\n  multiplier = 1.5000e+00.\n   tolerance = 1.0000e-08.\n      kernel = exp(-t*t/4).\n\n[1/6] Computing weights... [60/60]\n[2/6] Solving Lyapunov equation...\n[3/6] Solving SVD...\n[4/6] Transforming (P=+9)...\n[5/6] Solving eigen decomposition...\n[6/6] Done.\n\nM = \n+1.1745193571738943e+01+6.4089561283054790e-107j\n-5.5143304351134397e+00+5.7204056791636839e+00j\n-5.5143304351134397e+00-5.7204056791636839e+00j\n-1.6161617424833762e-02+2.3459542440459513e+00j\n-1.6161617424833762e-02-2.3459542440459513e+00j\n+1.6338578576177487e-01+1.9308431539218418e-01j\n+1.6338578576177487e-01-1.9308431539218418e-01j\n-5.4905134221689715e-03+2.2104939243740062e-03j\n-5.4905134221689715e-03-2.2104939243740062e-03j\nS = \n+1.8757961592204051e+00-0.0000000000000000e+00j\n+1.8700580506914817e+00+6.2013413918954552e-01j\n+1.8700580506914817e+00-6.2013413918954552e-01j\n+1.8521958553280000e+00-1.2601975249082220e+00j\n+1.8521958553280000e+00+1.2601975249082220e+00j\n+1.8197653300065935e+00+1.9494562062795735e+00j\n+1.8197653300065935e+00-1.9494562062795735e+00j\n+1.7655956664692953e+00-2.7555720406099038e+00j\n+1.7655956664692953e+00+2.7555720406099038e+00j\n\nRunning time: 3112 ms.\n```\n\n![exp(-t^2/4)](resource/example.png)\n\n#### Arbitrary Kernel\n\nFor arbitrary kernel, it is necessary to provide the kernel function in a text file.\nThe file should contain the kernel expressed as a function of variable `t`.\n\nThe `exprtk` is used to parse the expression and compute the value.\nThe provided kernel function must be valid and supported by `exprtk`.\nCheck the [documentation](https://www.partow.net/programming/exprtk/) regarding how to write a valid expression.\n\nFor example, to compute the approximation of `exp(-t^2/10)`, one can create a file `kernel.txt` with the following\ncontent:\n\n```text\nexp(-t*t/10)\n```\n\nIn the following, the kernel function is echoed to a file and then used as an input to the application.\n\n```bash\necho \"exp(-t*t/10)\" \u003e kernel.txt\n ./vpmr -n 60 -k kernel.txt -e 1e-12\n```\n\n![exp(-t^2/10)](resource/arbitrary.png)\n\n## Performance\n\nThe computation of weights, that involves integrals, and SVD are parallelised.\nA typical profiling would yield something similar to the following.\n\n![profiling](resource/profile.png)\n\n## Compilation\n\n\u003e [!WARNING]\n\u003e The application relies on `eigen` and `exprtk`, which depend on very heavy usage of templates.\n\u003e The compilation would take minutes and around 2 GB memory.\n\u003e You need to install libraries `gmp`, `mpfr` and `tbb` before compiling.\n\n### Docker\n\nTo avoid the hassle of installing dependencies, you can use the provided `Dockerfile`.\nFor example,\n\n```bash\nwget -q https://raw.githubusercontent.com/TLCFEM/vpmr/master/Dockerfile\ndocker build -t vpmr -f Dockerfile .\n```\n\nOr you simply pull using the following command.\n\n```bash\ndocker pull tlcfem/vpmr\n# or using GitHub Container Registry\ndocker pull ghcr.io/tlcfem/vmpr\n```\n\n### Windows\n\nUse the following instructions based on [MSYS2](https://www.msys2.org/), or follow the Linux instructions below with\nWSL.\n\n```bash\n# install necessary packages\npacman -S git mingw-w64-x86_64-cmake mingw-w64-x86_64-tbb mingw-w64-x86_64-gcc mingw-w64-x86_64-ninja mingw-w64-x86_64-gmp mingw-w64-x86_64-mpfr\n# clone the repository\ngit clone --recurse-submodules --depth 1 https://github.com/TLCFEM/vpmr.git\ncd vpmr\n# apply patch to enable parallel evaluation of some loops in SVD\ncd eigen \u0026\u0026 git apply --ignore-space-change --ignore-whitespace ../patch_size.patch \u0026\u0026 cd ..\n# configure and compile\ncmake -G Ninja -DCMAKE_BUILD_TYPE=Release .\nninja\n```\n\n### Linux\n\nThe following is based on Fedora.\n\n```bash\nsudo dnf install gcc g++ gfortran cmake git -y\nsudo dnf install tbb-devel mpfr-devel gmp-devel -y\ngit clone --recurse-submodules --depth 1 https://github.com/TLCFEM/vpmr.git\ncd vpmr\ncd eigen \u0026\u0026 git apply --ignore-space-change --ignore-whitespace ../patch_size.patch \u0026\u0026 cd ..\ncmake -DCMAKE_BUILD_TYPE=Release .\nmake\n```\n\n## Binary\n\nThe binary requires available `gmp`, `mpfr` and `tbb` libraries.\n\n```bash\n❯ ldd vpmr\n    linux-vdso.so.1 (0x00007ffec2fa0000)\n    libtbb.so.12 =\u003e /lib/x86_64-linux-gnu/libtbb.so.12 (0x00007fd1dcb13000)\n    libgmp.so.10 =\u003e /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fd1dca92000)\n    libmpfr.so.6 =\u003e /lib/x86_64-linux-gnu/libmpfr.so.6 (0x00007fd1dc9d8000)\n    libstdc++.so.6 =\u003e /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fd1dac00000)\n    libm.so.6 =\u003e /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd1daf20000)\n    libgcc_s.so.1 =\u003e /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fd1daf00000)\n    libc.so.6 =\u003e /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd1daa1f000)\n    /lib64/ld-linux-x86-64.so.2 (0x00007fd1dcb78000)\n```\n\nThe distributed `appimage` is portable.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftlcfem%2Fvpmr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftlcfem%2Fvpmr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftlcfem%2Fvpmr/lists"}