Skip to content

Commit

Permalink
rename package to randvec, polish setup.py and README, install pytest…
Browse files Browse the repository at this point in the history
… in github action, add Makefile
  • Loading branch information
jakobbossek committed Mar 23, 2023
1 parent 777ebd4 commit 52b1aac
Show file tree
Hide file tree
Showing 13 changed files with 220 additions and 120 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
strategy:
matrix:
# Run in all these versions of Python
python-version: ["3.9", "3.10"]
python-version: ["3.9", "3.10", "3.11"]

steps:
# Checkout the latest code from the repo
Expand All @@ -35,12 +35,12 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install matplotlib
pip install pytest
# Display the Python version being used
- name: Display Python version
run: python -c "import sys; print(sys.version)"

# Run the tests. I'm using pytest and the file is in the tests directory.
# Run the tests
- name: Run tests with pytest
run: pytest -v
5 changes: 5 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
exclude visualise.py
exclude setup.cfg
exclude Makefile
exclude publish.sh
exclude pyproject.toml_bck
49 changes: 49 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# clean-up
clean:
rm -rfv build dist randvec.egg-info \_\_pycache\_\_

# clean-up cache (TODO: does not work yet)
clean-pycache:
find . | grep -E "(/__pycache__$|\.pyc$|\.pyo$)" | xargs rm -rf

upgrade:
# Make sure you have the latest version of PyPA’s build installed
python -m pip install --user --upgrade setuptools wheel
python -m pip install --upgrade build
python -m pip install --upgrade twine

# source distribution
build:
python -m build

# upload to TestPyPi (see ~/.pypirc for token)
testpypi-upload:
python -m twine upload --repository testpypi dist/*

testpypi-web:
open https://test.pypi.org/project/randvec

# install TestPyPi version
testpypi-install:
python -m pip install --index-url https://test.pypi.org/simple/ --no-deps randvec

# upload to PyPi (see ~/.pypirc for token)
pypi-upload:
python -m twine upload dist/*

pypi-web:
open https://pypi.org/project/randvec

# install PyPi version
pypi-install:
python -m pip install randvec

install-local:
pip install --editable .

test:
pytest -v

flake8:
flake8

18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Random Probability Vectors
# Random vectors with sum one

This python3 module implements a method 'rpv' which allow to generate d-dimensional probability vectors where the sum of the components adds up to one. The function offers different methods as discussed in [1].
This Python3 module implements different approaches [1] to randomly and uniformly generate d-dimensional vectors whose components sum up to one.

[1] Maziero, J. Generating Pseudo-Random Discrete Probability Distributions. Brazilian Journal of Physics 45, 377–382 (2015). https://doi.org/10.1007/s13538-015-0337-8

Expand All @@ -10,26 +10,26 @@ This python3 module implements a method 'rpv' which allow to generate d-dimensio
Run the following to install the module:

```bash
$ pip install pyrpv
pip install randvec
```

## Usage

```python
from pyrpv import rpv
from randvec.methods import sample

# Generate 10 4-dimensional vectors with the simplex-method
rpv(10, 4, method = "simplex")
sample(10, 4, method = "simplex")

# Generate 10 3-dimensional vectors with the trigonometric methdod with subsequent shuffling
rpv(10, 3, method = "trigonometric", shuffle = True)
sample(10, 3, method = "trigonometric", shuffle = True)
```

# Developing pyrpv
# Developing randvec

To install the **pyrpv** module along with the tools you need to develop and run test, run the following command in your *virtual environment* (virtualenv):
To install the **randvec** module along with the tools you need to develop and run test, run the following command in your *virtual environment* (virtualenv):

```bash
$ pip install -e .[dev]
pip install -e .[dev]
```

29 changes: 0 additions & 29 deletions pyproject.toml

This file was deleted.

32 changes: 32 additions & 0 deletions pyproject.toml_bck
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "randvec"
version = "1.0.0"
authors = [
{ name="Jakob Bossek", email="j.bossek@gmail.com" },
]
description = "Generate random and uniform vectors whose components sum up to one"
readme = "README.md"
requires-python = ">=3.7"
classifiers = [
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"License :: OSI Approved :: MIT License",
"Development Status :: 5 - Production/Stable",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Mathematics",
]

[project.urls]
"Homepage" = "https://github.com/jakobbossek/randvec"
"Bug Tracker" = "https://github.com/jakobbossek/randvec/issues"
File renamed without changes.
88 changes: 26 additions & 62 deletions src/pyrpv/rpv.py → randvec/methods.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
import random
import math
import matplotlib.pyplot as plt


def rpv(n: int, d: int, method: str = "normalisation", shuffle: bool = False) -> list[list[float]]:
def sample(n: int, d: int, method: str = "normalisation", shuffle: bool = False) -> list[list[float]]:
'''
Generates a list of random probability vectors (rpv) with different methods.
Generates a list of n d-dimensional random vectors whose elements sum up to one
with different methods.
Args:
n (int): desired number of vectors.
d (int): dimension.
method (str): desired method (see rpv_* functions in this module).
shuffle (bool): shall each rpv be randomly shuffled? Default is False.
method (str): desired method (see sample_* functions in this module).
shuffle (bool): shall each vector be randomly shuffled? Default is False.
Returns:
List of length n of d-dimensional lists.
'''
assert n >= 1
assert d >= 2

funs = {
'normalisation': rpv_normalisation,
'exponential': rpv_exponential,
'iterative': rpv_iterative,
'trigonometric': rpv_trigonometric,
'simplex': rpv_simplex
'normalisation': sample_normalisation,
'exponential': sample_exponential,
'iterative': sample_iterative,
'trigonometric': sample_trigonometric,
'simplex': sample_simplex
}
assert method in funs.keys()

Expand All @@ -49,9 +49,9 @@ def normalise(x: list[float]) -> list[float]:
return list(map(lambda e: e / sum(x), x))


def rpv_normalisation(n: int, d: int) -> list[list[float]]:
def sample_normalisation(n: int, d: int) -> list[list[float]]:
'''
Generates a list of random probability vectors (rpv) via normalisation.
Generates a list of random vectors via normalisation.
I.e., (1) each component is sampled from a U(0,1) distribution and subsequently
(2) each component is divided by the components' sum.
Expand All @@ -73,9 +73,9 @@ def rpv_normalisation(n: int, d: int) -> list[list[float]]:
return vecs


def rpv_iterative(n: int, d: int) -> list[list[float]]:
def sample_iterative(n: int, d: int) -> list[list[float]]:
'''
Generates a list of random probability vectors (rpv) via an iterative approach:
Generates a list of random vectors via an iterative approach:
I.e., the i-th component of the rpv is sampled uniformly at random from [0, s] where s is
the sum of the 0, ..., (i-1)st components. The last component is finally (1-s). This
way it is unsured that the vectors are normalised.
Expand All @@ -89,7 +89,7 @@ def rpv_iterative(n: int, d: int) -> list[list[float]]:
assert n >= 1
assert d >= 2

def sample_rpv_iterative(d):
def sample_sample_iterative(d):
s = 0.0
vec = [None] * d
for j in range(d - 1):
Expand All @@ -98,13 +98,13 @@ def sample_rpv_iterative(d):
vec[d - 1] = 1 - s
return vec

vecs = [sample_rpv_iterative(d) for _ in range(n)]
vecs = [sample_sample_iterative(d) for _ in range(n)]
return list(vecs)


def rpv_trigonometric(n: int, d: int) -> list[list[float]]:
def sample_trigonometric(n: int, d: int) -> list[list[float]]:
'''
Generates a list of random probability vectors (rpv) via a trigonometric method.
Generates a list of random vectors via a trigonometric method.
Section 5 in the following paper contains the details: Maziero, J. Generating Pseudo-Random
Discrete Probability Distributions. Brazilian Journal of Physics 45, 377–382 (2015).
https://doi.org/10.1007/s13538-015-0337-8)
Expand All @@ -118,7 +118,7 @@ def rpv_trigonometric(n: int, d: int) -> list[list[float]]:
assert n >= 1
assert d >= 2

def sample_rpv_trigonometric(d):
def sample_sample_trigonometric(d):
ts = [random.random() for _ in range(d - 1)]

# build vector of weights
Expand All @@ -137,12 +137,12 @@ def sample_rpv_trigonometric(d):

return vec

return [sample_rpv_trigonometric(d) for _ in range(n)]
return [sample_sample_trigonometric(d) for _ in range(n)]


def rpv_exponential(n: int, d: int) -> list[list[float]]:
def sample_exponential(n: int, d: int) -> list[list[float]]:
'''
Generates a list of random probability vectors (rpv) by means of the inverse
Generates a list of random vectors by means of the inverse
exponential distribution function: I.e., the i-th component of the rpv is sampled
uniformly at random from [0, s] where s is the sum of the 0, ..., (i-1)st
components. The last component is finally (1-s). This way it is unsured that
Expand All @@ -165,13 +165,12 @@ def rpv_exponential(n: int, d: int) -> list[list[float]]:
return vecs


def rpv_simplex(n: int, d: int) -> list[list[float]]:
def sample_simplex(n: int, d: int) -> list[list[float]]:
'''
Generates a list of random probability vectors (rpv) via simplex sampling.
Generates a list of random vectors via simplex sampling.
See [1] for details on this method.
[1] Grimme, C. Picking a Uniformly Random Point from an Arbitrary Simplex.
See the following paper for details on this method:
Grimme, C. Picking a Uniformly Random Point from an Arbitrary Simplex.
Technical Report. https://doi.org/10.13140/RG.2.1.3807.6968
Args:
Expand All @@ -197,38 +196,3 @@ def sample_vector_from_unit_simplex(d):

vecs = [list(sample_vector_from_unit_simplex(d)) for _ in range(n)]
return vecs


if __name__ == "__main__":
# parameters
n, d = 1000, 3

# plot
fig = plt.figure()

methods = ["normalisation", "iterative", "exponential", "simplex", "trigonometric"]
k = 1
for i, method in enumerate(methods):
for j, shuffle in enumerate([True, False]):
vecs = list(rpv(n, d, method = method, shuffle = shuffle))
# print(list(vecs))
ss = map(sum, vecs)
# print(list(ss))

sp = fig.add_subplot(1, 2 * len(methods), k, projection = '3d')
k += 1

xs = [x[0] for x in vecs]
ys = [x[1] for x in vecs]
zs = [x[2] for x in vecs]

sp.set_xlabel('x')
sp.set_ylabel('y')
sp.set_zlabel('z')
title = method
if shuffle:
title += " (shuffled)"
sp.set_title(title)
sp.scatter(xs, ys, zs, marker = 'o')

plt.show()
1 change: 1 addition & 0 deletions randvec/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "1.0.1"

0 comments on commit 52b1aac

Please sign in to comment.