Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Homogenized QCQP Class #12

Merged
merged 45 commits into from
Nov 21, 2024
Merged
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
9571dfd
Started script for simplified rotation synchronization example that i…
holmesco Jun 18, 2024
14464f0
Chordalizing ADMM now working for simple loop problem
holmesco Jun 19, 2024
37838fa
Fix minor issue with residual sign.
holmesco Jun 19, 2024
47ebab1
rot synch non-chordal admm with decomposed SDP works on small problems.
holmesco Jun 25, 2024
93e7786
Locking pose with constraint instead of cost. No longer having issues…
holmesco Jun 25, 2024
d732b9b
added script to compare run times
holmesco Jun 28, 2024
c14e7e3
Modified test so that locked pose is not on the main loop. Chain can …
holmesco Jul 3, 2024
4fa6ad5
admm working on new (lollipop) problem with and without decomposition.
holmesco Jul 3, 2024
6a81c34
Implemented adaptive penalty term. Started work on using standard lib…
holmesco Jul 5, 2024
5b871e1
Updated sparse solver to use junction tree for decomposed problem def…
holmesco Jul 5, 2024
a874794
Fixed issue: variable ordering was being inverted during clique defin…
holmesco Jul 5, 2024
5fb39ca
Added timing and iteration data to functions for more accurate compar…
holmesco Jul 5, 2024
51e2335
Created new general problem class to store information about problem,…
holmesco Sep 27, 2024
52bb6ec
Added test function for HomQCQP class
holmesco Sep 27, 2024
9516e72
Added ASG elim ordering, triangulation, and junction tree to HomQCQP …
holmesco Sep 30, 2024
7b0789a
Built and tested code for generating interclique constraints based on…
holmesco Oct 2, 2024
2d9ce0c
Wrote function to decompose an obj/constraint matrix into a set of ma…
holmesco Oct 12, 2024
e458ea9
Set up and tested decomposed solver.
holmesco Oct 14, 2024
b72569c
Integrated cholmod symbolic factorization. all tests passing.
holmesco Oct 20, 2024
127a355
Fixed locking pose error in rotation problem. Removed dead code from …
holmesco Oct 23, 2024
3849087
Added method to HomQCQP for extracting the standard form of a problem…
holmesco Oct 29, 2024
5e92f15
Fixed min rank completion (now using polar decomp).
holmesco Nov 5, 2024
7240d57
Improved speed of generating overlap constraints.
holmesco Nov 6, 2024
5ad5f8f
Fixed recursion issue with mosek fusion. Added input for variable lis…
holmesco Nov 8, 2024
9e8bd0e
Added greedy-cover method for matrix decomposition into cliques. Adde…
holmesco Nov 8, 2024
ca7b8ff
Added manual clique decomposition (i.e. can provide cliques as input).
holmesco Nov 12, 2024
e33ab89
Added and tested decomposed dual SDP solver.
holmesco Nov 13, 2024
d8a4bbc
Efficiency improvements for dual solver. Added changes for matrix-wei…
holmesco Nov 13, 2024
af5e404
Added a function to build the dual certificate matrix from the dual c…
holmesco Nov 14, 2024
7383968
minor fixes for testing dual decomposition
holmesco Nov 20, 2024
827e62e
Fix dependencies
duembgen Nov 21, 2024
551f5e4
Remove unused imports and get_overlap function
duembgen Nov 21, 2024
0aceffc
Create new clique testing
duembgen Nov 21, 2024
dd6a3ba
Merge branch 'main' into nonchordal-admm
duembgen Nov 21, 2024
1395626
Recover solve_sdp_homqcqp
duembgen Nov 21, 2024
42e9520
Fix lynt error
duembgen Nov 21, 2024
ebaed5b
Fixed linalg tests
duembgen Nov 21, 2024
d3a4e8c
Fix lynt again
duembgen Nov 21, 2024
7088d48
Move rot_synch class to _test/utils.py
duembgen Nov 21, 2024
03ced04
Fixed bug in process_cliques with list as input.
holmesco Nov 21, 2024
c2e95fd
Fix dependencies
duembgen Nov 21, 2024
c84b816
Merge branch 'main' into nonchordal-admm
duembgen Nov 21, 2024
5b7ca7a
Attempt to add MOSEK
duembgen Nov 21, 2024
85645d2
Remove python app workflow
duembgen Nov 21, 2024
38b846b
Merge branch 'nonchordal-admm' of github.com:utiasASRL/certifiable-to…
duembgen Nov 21, 2024
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
Prev Previous commit
Next Next commit
Fixed recursion issue with mosek fusion. Added input for variable lis…
…t when finding a minimum rank completion.
holmesco committed Nov 8, 2024
commit 5ad5f8f8d93ed9141753b9750e8e65c364f9b0b3
18 changes: 16 additions & 2 deletions _scripts/wafr_problems.py
Original file line number Diff line number Diff line change
@@ -72,23 +72,37 @@ def process_problems(fname="_examples/mw_loc_3d_small.pkl"):
pickle.dump(df, file)


def test_problem(fname="_examples/mw_loc_3d_small.pkl", id=8):
def test_problem(
fname="_examples/mw_loc_3d_small.pkl",
id=8,
):
problem, df = load_problem(fname=fname, id=id)

problem.plot_asg(remove_vars=["h"], html="asg.html")
problem.plot_ctree(html="ctree.html")

# Solve standard SDP
# X, info, solve_time = solve_sdp_homqcqp(problem, tol=1e-10, verbose=True)

# Solve decomposed SDP
clq_list, info = solve_dsdp(problem, tol=1e-10, verbose=True)
Y, ranks, factor_dict = problem.get_mr_completion(clq_list)

# Check solution
assert Y.shape[1] == 1, ValueError("Decomposed solution is not rank 1")
x = []
for varname in df.var_sizes.keys():
x.append(factor_dict[varname].flatten())
x = np.concatenate(x)
np.testing.assert_allclose(
x, df.x_gt_init, atol=5e-5, err_msg="solution doesn't match"
)


if __name__ == "__main__":
test_problem(fname="_examples/mw_loc_3d_small.pkl")
# test_problem(fname="_examples/mw_loc_3d_small.pkl")
# test_problem(fname="_examples/mw_loc_3d.pkl")
# test_problem(fname="_examples/rangeonlyloc2d_no_const-vel_small.pkl")
test_problem(fname="_examples/rangeonlyloc2d_no_const-vel.pkl", id=27)
# process_problems(fname="_examples/mw_loc_3d_small.pkl")
# process_problems(fname="_examples/rangeonlyloc2d_no_const-vel_small.pkl")
11 changes: 8 additions & 3 deletions cert_tools/hom_qcqp.py
Original file line number Diff line number Diff line change
@@ -74,6 +74,8 @@ def remove_dependent_constraints(self):
# Remove dependent constraints
self.As = [self.As[i] for i in range(len(self.As)) if i not in bad_idx]

return bad_idx

def get_asg(self, rm_homog=False):
"""Generate Aggregate Sparsity Graph for a given problem. Note that values
of the matrices are irrelevant.
@@ -88,7 +90,7 @@ def get_asg(self, rm_homog=False):

# Combine cost and constraints
# NOTE: The numerical values here do not matter, just whether or not an element of the matrix is filled.
pmat = self.C
pmat = self.C.copy()
for A in self.As:
pmat += A
# build variable dictionaries
@@ -459,13 +461,14 @@ def factor_psd_mat(mat, rank_tol=1e5):

return factor, r

def get_mr_completion(self, clique_mats, rank_tol=1e5, debug=False):
def get_mr_completion(self, clique_mats, var_list=None, rank_tol=1e5, debug=False):
"""Complete a positive semidefinite completable matrix using the
minimum-rank completion as proposed in:
Jiang, Xin et al. “Minimum-Rank Positive Semidefinite Matrix Completion with Chordal Patterns and Applications to Semidefinite Relaxations.”

Args:
clique_mats (list): list of nd-arrays representing the SDP solution (per clique)
var_list (list): list of keys corresponding to the desired variable ordering. If None, then the object var_list is used
rank_tol (_type_, optional): Tolerance for determining rank. Defaults to 1e5.
"""
r_max = 0 # max rank found
@@ -518,8 +521,10 @@ def get_mr_completion(self, clique_mats, rank_tol=1e5, debug=False):
factor_dict[key] = U_Q[inds, :]

# Construct full factor
if var_list is None:
var_list = self.var_list
Y = []
for varname in self.var_list:
for varname in var_list:
Y.append(factor_dict[varname])
Y = np.vstack(Y)
return Y, ranks, factor_dict
8 changes: 3 additions & 5 deletions cert_tools/sparse_solvers.py
Original file line number Diff line number Diff line change
@@ -202,15 +202,13 @@ def get_decomp_fusion_expr(pmat_in):
# decompose matrix
mat_decomp = problem.decompose_matrix(pmat_in, decomp_method)
# add clique components to fusion expression
expr = None
expr_sum_list = []
for k, pmat in mat_decomp.items():
clique = cliques[k]
mat_k = pmat.get_matrix(variables=clique.var_sizes)
mat_k_fusion = sparse_to_fusion(mat_k)
if expr is None:
expr = fu.Expr.dot(mat_k_fusion, cvars[k])
else:
expr += fu.Expr.dot(mat_k_fusion, cvars[k])
expr_sum_list.append(fu.Expr.dot(mat_k_fusion, cvars[k]))
expr = fu.Expr.add(expr_sum_list)
return expr

# OBJECTIVE