This repository containts the python implementation of the cosine measure and cosine vector calculation, based on the algorithm created in the paper titled "The cosine measure relative to a subspace" by Audet, Hare & Jarry‑Bolduc, 2025, published in Computational Optimization and Applications.
This is a translation and extension of the original MATLAB version. It checks whether a given set of vectors positively spans a subspace, and returns the cosine measure and if requested, the associated cosine vector.
- Cosine Measure (
cm): Gives a value in [-1, 1] that shows how well the set aligns with a subspace. - Cosine Vector (
cv): A unit vector in the subspace that hits the cosine measure. - Diagnostics (
info): Data about the run including active set, rank info, whether it positively spans, and more.
cm, cv, info = cmrel(D, **options)D:numpy.ndarrayof shape(n, q), where each column is a vector in ℝⁿ.options(optional):subspace: Custom subspace matrix (default = span(D)).cosine_vector: Set to 1 (default) to compute cosine vector, or 0 to skip.epsilon: Threshold for numerical noise. Default is1e-3.
cm: Cosine measure (float).cv: Cosine vector (unit vector in the subspace, if requested).cvis an empty list ([]) when cosine_vector = 0.info: Dictionary containing:'proj_D_normalized': Normalized projected vectors'rank_D','dim_subspace''p_spanning_L':'yes'or'no''active_set': Subset of D that achieves the cosine measure'zero_vector': Indicates fallback to nullspace-based vector'time': Total runtime
import numpy as np
from cmrel import cmrel
D = np.array([
[1, 0],
[0, 1],
[1, 1]
]).T
cm, cv, info = cmrel(D)
print("Cosine Measure:", cm)
print("Cosine Vector:", cv)
print("Info:", info)This script can be run from the terminal, with a given input file, as follows:
run_cmrel.py
python run_cmrel.py path/to/your_vectors.txt --subspace path/to/subspace.txt --no-cvfile: Path to a.txtfile, where each row is a vector (space-separated).--subspace: (Optional) Path to a subspace file in the same format.--no-cv: (Optional) Flag to skip computing the cosine vector.
├── cmrel.py # Main algorithm
├── utils.py # Helper functions: projection, normalization, etc.
├── run_cmrel.py # Optional entry point (if using command line input)
├── test_cmrel.py # Pytest for cmrel
├── test_utils.py # Pytest for helper functions
├── test_utils.py # Pytest for helper functions
├── matlab_code # Folder containing original matlab code
├──── cmpss.m # cosine measure of a finite positive spanning set
├──── cmrel-new.m # original cmrel code in matlab (most recently updated)
├──── cmrel.m # original cmrel code in matlab
├──── cmrel2.m # original cmrel code in matlab
├──── cmrelss.m # cosine measure value and cosine vector set relative to a linear subspace L
└── readme.md # This file
To run all tests:
pytest -vTo run a specific test:
pytest -k test_pspan_equals_L -v- Requires:
numpy,cvxpy,scipy,mpmath,pytest - Uses the
CLARABELsolver (can be changed in code if needed) - Handles edge cases: empty input, fallback if cosine vector is zero
For future development, in cmrel.py, the info variable is defined as a dictionary, the equivalent of the matlab info.blank. To potentially expand this code, as a package, etc, CmRel info could be defined as a data class.
This was built as part of a research implementation and translation from MATLAB to Python.
Author: Dr. Gabriel Jarry-Bolduc (gabjarry@aus.edu)
Research Assistant: Joban Brar (jbrar623@mtroyal.ca)