Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.5] - 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
30 changes: 27 additions & 3 deletions _test/utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
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

# Global Defaults
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
Expand All @@ -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):
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion cert_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
from .linalg_tools import *
from .sdp_solvers import *

__version__ = "0.0.3"
__version__ = "0.0.5"
10 changes: 7 additions & 3 deletions cert_tools/eopt_solvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
)

Expand Down
5 changes: 3 additions & 2 deletions cert_tools/hom_qcqp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
19 changes: 6 additions & 13 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,12 @@ 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

- suitesparse # required for sparseqr
- pip:
- -r requirements.txt
- -e .
- -e .
10 changes: 2 additions & 8 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
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
# packages that cannot be installed by install_requires or conda
sparseqr
21 changes: 10 additions & 11 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = cert_tools
version = 0.0.3
version = 0.0.5
authors = [
{name = "Frederike Dümbgen", email = "frederike.dumbgen@utoronto.ca" },
{name = "Connor Holmes", email = "connor.holmes@mail.utoronto.ca" }]
Expand All @@ -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.1#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]
Expand Down