From 8df7969f9d90a6311f5b074955ba51444f7e1591 Mon Sep 17 00:00:00 2001 From: Frederike Duembgen Date: Tue, 27 May 2025 16:27:23 -0400 Subject: [PATCH 01/10] Update requirements --- requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index ebc238d..8f00bba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,7 @@ -sparseqr>=1.2.1 gurobipy==10.0.3 quadprog==0.1.11 cvxopt>=1.3.2 igraph>=0.11.8 asrl-pylgmath>=1.0.3 chompack>=2.3.2 -git+https://github.com/utiasASRL/poly_matrix.git@v0.2 +git+https://github.com/utiasASRL/poly_matrix.git@v0.3 From 8574d8451051eba531b2d7292fe5c967c13b98c8 Mon Sep 17 00:00:00 2001 From: Frederike Duembgen Date: Tue, 27 May 2025 17:34:20 -0400 Subject: [PATCH 02/10] Remove pylgmath dependency --- _test/utils.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/_test/utils.py b/_test/utils.py index 9905cc9..d3e98c0 100644 --- a/_test/utils.py +++ b/_test/utils.py @@ -1,6 +1,6 @@ import numpy as np from poly_matrix import PolyMatrix -from pylgmath import so3op +from scipy.spatial.transform import Rotation as R from cert_tools import HomQCQP @@ -8,6 +8,30 @@ ER_MIN = 1e6 +def vec2rot(aaxis_ba): + """Replacement for pylgmath.so3.operations.vec2rot""" + mats = [] + if np.ndim(aaxis_ba) == 3: + for ai in aaxis_ba: + assert ai.shape[-1] == 1 + r = R.from_rotvec(ai[:, 0]) + mats.append(r.as_matrix()) + mat = np.stack(mats) + elif np.ndim(aaxis_ba) == 2: + assert aaxis_ba.shape[-1] == 1 + r = R.from_rotvec(aaxis_ba[:, 0]) + mat = r.as_matrix() + + # For performance, we can switch back to using pylgmath. + # For now it was removed to avoid dependeny for one function only. + # Below was ensured to pass before removing dependncy. + # + # from pylgmath import so3op + # mat_test = so3op.vec2rot(aaxis_ba) + # np.testing.assert_allclose(mat, mat_test) + return mat + + class RotSynchLoopProblem(HomQCQP): """Class to generate and solve a rotation synchronization problem with loop constraints. The problem is generated with ground truth rotations and noisy @@ -34,7 +58,7 @@ def __init__(self, N=10, sigma=1e-3, loop_pose=3, locked_pose=0, seed=0): np.random.seed(seed) # generate ground truth poses aaxis_ab_rand = np.random.uniform(-np.pi / 2, np.pi / 2, size=(N, 3, 1)) - R_gt = so3op.vec2rot(aaxis_ab_rand) + R_gt = vec2rot(aaxis_ab_rand) # Associated variable list self.var_sizes = {"h": 1} for i in range(N): @@ -44,7 +68,7 @@ def __init__(self, N=10, sigma=1e-3, loop_pose=3, locked_pose=0, seed=0): self.locked_pose = str(locked_pose) # Pose locked at this pose self.meas_dict = {} for i in range(0, N): - R_pert = so3op.vec2rot(sigma * np.random.randn(3, 1)) + R_pert = vec2rot(sigma * np.random.randn(3, 1)) if i == N - 1: if loop_pose > 0: j = loop_pose From fc3267ab6d685ef4d6d22864b16cbd908c81f5dd Mon Sep 17 00:00:00 2001 From: Frederike Duembgen Date: Tue, 27 May 2025 17:35:25 -0400 Subject: [PATCH 03/10] Remove panadas dependency --- cert_tools/eopt_solvers.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cert_tools/eopt_solvers.py b/cert_tools/eopt_solvers.py index 2b53902..9b8ebe4 100644 --- a/cert_tools/eopt_solvers.py +++ b/cert_tools/eopt_solvers.py @@ -3,11 +3,11 @@ import mosek import numpy as np import numpy.linalg as la -import pandas as pd import scipy.sparse as sp +from scipy.optimize import linprog + from cert_tools.eig_tools import get_min_eigpairs from cert_tools.linalg_tools import get_nullspace -from scipy.optimize import linprog # Number of eigenvalues to compute EIG_METHOD = "direct" # "lobpcg" @@ -474,6 +474,10 @@ def solve_eopt_cuts( """Solve the certificate/eigenvalue optimization problem using a cutting plane algorithm. Current algorithm uses the level method with the target level at a tolerance below zero """ + print( + "Warning: when using this function, you might want to convert iter_info to a pandas Dataframe." + "This used to be the default behavior but was removed to avoid pandas dependency." + ) # Initialize cut plane model m = CutPlaneModel(xinit.shape[0], A_eq=A_eq, b_eq=b_eq) # Intialize status vars for optimization @@ -589,7 +593,7 @@ def solve_eopt_cuts( gap=gap, t_min=t_min, t_max=t_max, - iter_info=pd.DataFrame(iter_info), + iter_info=iter_info, model=m, ) From bf2af1138a09a2655d76c41a9e71b017cdee6c4f Mon Sep 17 00:00:00 2001 From: Frederike Duembgen Date: Tue, 27 May 2025 17:36:01 -0400 Subject: [PATCH 04/10] Move plotly import to inside the (only) function that uses it. --- cert_tools/hom_qcqp.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cert_tools/hom_qcqp.py b/cert_tools/hom_qcqp.py index db9d169..02dde0c 100644 --- a/cert_tools/hom_qcqp.py +++ b/cert_tools/hom_qcqp.py @@ -5,8 +5,6 @@ import igraph as ig import matplotlib.pyplot as plt import numpy as np -import plotly.graph_objects as go -import plotly.io as pio import scipy.sparse as sp from cvxopt import amd, spmatrix from igraph import Graph @@ -735,6 +733,9 @@ def get_slices(self, mat, var_list_row, var_list_col=[]): def plot_graph(graph, **kwargs): + import plotly.graph_objects as go + import plotly.io as pio + layout = kwargs.get("layout", graph.layout("kk")) vertex_label = kwargs.get( "vertex_label", graph.vs["name"] if "name" in graph.vs.attributes() else None From d267c8ed1c2783cf360ae3b6a6c8e01cd88c94f5 Mon Sep 17 00:00:00 2001 From: Frederike Duembgen Date: Tue, 27 May 2025 17:38:01 -0400 Subject: [PATCH 05/10] Clean up dependencies --- environment.yml | 18 +++++------------- requirements.txt | 8 +------- setup.cfg | 19 +++++++++---------- 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/environment.yml b/environment.yml index 630dde4..4ad451a 100644 --- a/environment.yml +++ b/environment.yml @@ -9,19 +9,11 @@ dependencies: - python=3.10 - pip=22.3 - - numpy>=1.23.5 - - scipy==1.9.1 - - matplotlib>=3.6.2 - - pandas>=1.5.3 - - cvxpy>=1.3.2 - - pytest>=7.2.2 - - black>=23.1.0 - - mosek>=11 - - casadi>=3.6.3 - - scikit-sparse>=0.4.14 - - plotly>=5.24.1 - - suitesparse + # packages for local development that are not installed by setup.cfg + - black>=23.1 + - plotly>=5.24 + - pytest - pip: - -r requirements.txt - - -e . + - -e . diff --git a/requirements.txt b/requirements.txt index 8f00bba..9fd34de 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1 @@ -gurobipy==10.0.3 -quadprog==0.1.11 -cvxopt>=1.3.2 -igraph>=0.11.8 -asrl-pylgmath>=1.0.3 -chompack>=2.3.2 -git+https://github.com/utiasASRL/poly_matrix.git@v0.3 +# packages that cannot be installed by install_requires or conda diff --git a/setup.cfg b/setup.cfg index bb9e146..f0e1a6f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,18 +16,17 @@ license = { file="LICENSE" } [options] packages = find: install_requires = - casadi - matplotlib - numpy - pandas - scipy - mosek - cvxpy - igraph + casadi>=3.6 # used for BM interface to IPOPT + cvxpy>=1.3 + matplotlib>=3.6 + mosek>=11 + numpy>=1.23 + scipy==1.9 + igraph # for aggregate sparsity definition chompack - plotly + poly_matrix @ git+https://github.com/utiasASRL/poly_matrix.git@v0.3#egg=poly_matrix -[options.packages.find] # do not mistake tests/ for a package directory +[options.packages.find] # do not mistake _tests/ for a package directory exclude=_test* [flake8] From 1f6bedcf82119b93b613eed9fbdea9b3d14a05e5 Mon Sep 17 00:00:00 2001 From: Frederike Duembgen Date: Tue, 27 May 2025 17:47:03 -0400 Subject: [PATCH 06/10] Bump version to 0.0.4 and add CHANGELOG --- CHANGELOG.md | 23 +++++++++++++++++++++++ cert_tools/__init__.py | 2 +- environment.yml | 1 + setup.cfg | 2 +- 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ad7526b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,23 @@ +# CHANGELOG +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] - YYYY-MM-DD + +### Added + +### Changed + +### Fixed + +## [0.0.4] - 2025-05-27 + +### Added +- This CHANGELOG, to keep track of new releases in the future. + +### Changed +- Remove unnecessary dependencies (pandas, pylgmath, gurobipy) +- Make some dependencies optional (plotly, sparseqr) +- More consistent use of install_requires, requirements.txt, environment.yml diff --git a/cert_tools/__init__.py b/cert_tools/__init__.py index 6e079ab..f582858 100644 --- a/cert_tools/__init__.py +++ b/cert_tools/__init__.py @@ -4,4 +4,4 @@ from .linalg_tools import * from .sdp_solvers import * -__version__ = "0.0.3" +__version__ = "0.0.4" diff --git a/environment.yml b/environment.yml index 4ad451a..bf79b23 100644 --- a/environment.yml +++ b/environment.yml @@ -13,6 +13,7 @@ dependencies: - black>=23.1 - plotly>=5.24 - pytest + - sparseqr - pip: - -r requirements.txt diff --git a/setup.cfg b/setup.cfg index f0e1a6f..d7e6be7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = cert_tools -version = 0.0.3 +version = 0.0.4 authors = [ {name = "Frederike Dümbgen", email = "frederike.dumbgen@utoronto.ca" }, {name = "Connor Holmes", email = "connor.holmes@mail.utoronto.ca" }] From c8d8a6d198f15047733a6faad807217d7b282dff Mon Sep 17 00:00:00 2001 From: Frederike Duembgen Date: Tue, 27 May 2025 17:48:23 -0400 Subject: [PATCH 07/10] Move sparseqr --- environment.yml | 1 - requirements.txt | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index bf79b23..4ad451a 100644 --- a/environment.yml +++ b/environment.yml @@ -13,7 +13,6 @@ dependencies: - black>=23.1 - plotly>=5.24 - pytest - - sparseqr - pip: - -r requirements.txt diff --git a/requirements.txt b/requirements.txt index 9fd34de..5930804 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ # packages that cannot be installed by install_requires or conda +sparseqr From 8f93713d003484afcf83a99d1a6ae78c8a148d2f Mon Sep 17 00:00:00 2001 From: Frederike Duembgen Date: Tue, 27 May 2025 18:31:47 -0400 Subject: [PATCH 08/10] Bump poly_matrix version --- cert_tools/__init__.py | 2 +- setup.cfg | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cert_tools/__init__.py b/cert_tools/__init__.py index f582858..59fea62 100644 --- a/cert_tools/__init__.py +++ b/cert_tools/__init__.py @@ -4,4 +4,4 @@ from .linalg_tools import * from .sdp_solvers import * -__version__ = "0.0.4" +__version__ = "0.0.5" diff --git a/setup.cfg b/setup.cfg index d7e6be7..92320b7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = cert_tools -version = 0.0.4 +version = 0.0.5 authors = [ {name = "Frederike Dümbgen", email = "frederike.dumbgen@utoronto.ca" }, {name = "Connor Holmes", email = "connor.holmes@mail.utoronto.ca" }] @@ -24,7 +24,7 @@ install_requires = scipy==1.9 igraph # for aggregate sparsity definition chompack - poly_matrix @ git+https://github.com/utiasASRL/poly_matrix.git@v0.3#egg=poly_matrix + poly_matrix @ git+https://github.com/utiasASRL/poly_matrix.git@v0.3.1#egg=poly_matrix [options.packages.find] # do not mistake _tests/ for a package directory exclude=_test* From a86e82be43e931519508bf515139891e57a99cf1 Mon Sep 17 00:00:00 2001 From: Frederike Duembgen Date: Tue, 27 May 2025 19:16:25 -0400 Subject: [PATCH 09/10] Add suitesparse --- environment.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/environment.yml b/environment.yml index 4ad451a..238a9ef 100644 --- a/environment.yml +++ b/environment.yml @@ -14,6 +14,7 @@ dependencies: - plotly>=5.24 - pytest + - suitesparse # required for sparseqr - pip: - -r requirements.txt - -e . From 568681c35f6d07ae7b92a49a3b73174c86fd5ba6 Mon Sep 17 00:00:00 2001 From: Frederike Duembgen Date: Tue, 27 May 2025 21:39:29 -0400 Subject: [PATCH 10/10] Update version in CHANGELOG --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad7526b..a59ac4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed ### Fixed - -## [0.0.4] - 2025-05-27 + +## [0.0.5] - 2025-05-27 ### Added - This CHANGELOG, to keep track of new releases in the future.