Coverage for src / cvx / ball / solver.py: 100%
11 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-23 12:04 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-23 12:04 +0000
1"""Convex utilities for computing the minimum enclosing circle/ball.
3Provides a CVXPY-based solver for the smallest enclosing ball problem used by
4tests and experiments in this repository.
5"""
7from typing import Any
9import cvxpy as cp
10import numpy as np
13def min_circle_cvx(points: np.ndarray, **kwargs: dict[str, Any]) -> tuple[float, np.ndarray]:
14 """Compute the smallest enclosing circle for a set of points using convex optimization.
16 This function solves the convex optimization problem to find the minimum radius
17 circle that contains all the given points. It uses a second-order cone constraint
18 to enforce that all points lie within the circle.
20 Args:
21 points: A numpy array of shape (n, d) where n is the number of points
22 and d is the dimension of the space.
23 **kwargs: Additional keyword arguments to pass to the solver.
24 Common options include 'solver' to specify which CVXPY solver to use.
26 Returns:
27 A tuple containing:
28 - The radius of the minimum enclosing circle (float)
29 - The center coordinates of the circle (numpy.ndarray)
31 Example:
32 >>> import numpy as np
33 >>> from cvx.ball.solver import min_circle_cvx
34 >>> points = np.array([[0, 0], [1, 0], [0, 1]])
35 >>> radius, center = min_circle_cvx(points, solver="CLARABEL")
36 """
37 # cvxpy variable for the radius
38 r = cp.Variable(shape=1, name="Radius")
39 # cvxpy variable for the midpoint
40 x = cp.Variable(points.shape[1], name="Midpoint")
41 objective = cp.Minimize(r)
42 constraints = [
43 cp.SOC(
44 r * np.ones(points.shape[0]),
45 points - cp.outer(np.ones(points.shape[0]), x),
46 axis=1,
47 )
48 ]
50 problem = cp.Problem(objective=objective, constraints=constraints)
51 problem.solve(**kwargs)
53 return r.value[0], x.value