Skip to content

Commit 5f0d38a

Browse files
Transurgeonclaude
andauthored
remove redundant nonsmooth methods, add types and docs (#158)
* Address review comments: remove redundant nonsmooth methods, add types, docs - Remove is_atom_nonsmooth_convex/is_atom_nonsmooth_concave from base Atom class and 10 atom subclasses; use existing is_atom_convex/is_atom_concave in DNLP composition rules instead - Add type annotations and docstrings to NLPsolver, Bounds, and Oracles in nlp_solver.py - Document Variable.sample_bounds with class-level type annotation and docstring - Revert GENERAL_PROJECTION_TOL back to 1e-10 (was loosened for removed IPOPT derivative checker) - Update CLAUDE.md atom classification docs to reflect simplified API Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Move sample_bounds docs from #: comments into Variable class docstring Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8b37442 commit 5f0d38a

15 files changed

Lines changed: 91 additions & 92 deletions

File tree

CLAUDE.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ Adding a new diff engine atom requires:
159159

160160
The diff engine supports CVXPY `Parameter` objects: `C_problem` registers parameters with the C engine and `update_params()` re-pushes values without rebuilding the expression tree. Sparse parameter values are fused into sparse matmul operations.
161161

162-
`DerivativeChecker` in `nlp_solver.py` provides finite-difference verification of gradients, Jacobians, and Hessians during development.
162+
`DerivativeChecker` in `cvxpy/tests/nlp_tests/derivative_checker.py` provides finite-difference verification of gradients, Jacobians, and Hessians during development.
163163

164164
Key files in `cvxpy/reductions/solvers/nlp_solvers/diff_engine/`:
165165
- `converters.py` - Converts CVXPY expression AST to C diff engine trees. Contains `ATOM_CONVERTERS` dict mapping ~40 atom types to C constructors. Includes optimizations like sparse parameter matmul fusion.
@@ -182,17 +182,17 @@ Convention: all arrays are flattened in **Fortran order** ('F') for column-major
182182
1. Create a canonicalizer in `cvxpy/reductions/dnlp2smooth/canonicalizers/`
183183
2. The canonicalizer converts non-smooth atoms to smooth equivalents using auxiliary variables
184184
3. Register in `canonicalizers/__init__.py` by adding to `SMOOTH_CANON_METHODS` dict
185-
4. Classify the atom using the three-way atom-level API (see below)
185+
4. If the atom is smooth, override `is_atom_smooth()` to return `True` (see classification below)
186186

187-
### DNLP Atom Classification (Three-way)
187+
### DNLP Atom Classification
188188

189-
Each atom implements exactly one of three atom-level methods:
189+
Atoms are classified as smooth or non-smooth. Non-smooth atoms reuse the existing `is_atom_convex()`/`is_atom_concave()` methods for the DNLP composition rules—no separate method is needed.
190190

191191
| Category | Method | Examples |
192192
|---|---|---|
193193
| **Smooth** | `is_atom_smooth() → True` | exp, log, power, sin, prod, quad_form |
194-
| **NS-convex** | `is_atom_nonsmooth_convex() → True` | abs, max, norm1, norm_inf, huber |
195-
| **NS-concave** | `is_atom_nonsmooth_concave() → True` | min, minimum |
194+
| **Non-smooth convex** | `is_atom_convex() → True` (and not smooth) | abs, max, norm1, norm_inf, huber |
195+
| **Non-smooth concave** | `is_atom_concave() → True` (and not smooth) | min, minimum |
196196

197197
### DNLP Expression-level Rules
198198

cvxpy/atoms/atom.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,6 @@ def is_atom_smooth(self) -> bool:
192192
"""Is the atom smooth?"""
193193
return False
194194

195-
def is_atom_nonsmooth_convex(self) -> bool:
196-
"""Is the atom nonsmooth and convex?"""
197-
return False
198-
199-
def is_atom_nonsmooth_concave(self) -> bool:
200-
"""Is the atom nonsmooth and concave?"""
201-
return False
202-
203195
def is_atom_log_log_convex(self) -> bool:
204196
"""Is the atom log-log convex?
205197
"""
@@ -278,7 +270,7 @@ def is_linearizable_convex(self) -> bool:
278270
# Applies DNLP composition rule.
279271
if self.is_constant():
280272
return True
281-
elif self.is_atom_smooth() or self.is_atom_nonsmooth_convex():
273+
elif self.is_atom_smooth() or self.is_atom_convex():
282274
for idx, arg in enumerate(self.args):
283275
if not (arg.is_smooth() or
284276
(arg.is_linearizable_convex() and self.is_incr(idx)) or
@@ -287,15 +279,15 @@ def is_linearizable_convex(self) -> bool:
287279
return True
288280
else:
289281
return False
290-
282+
291283
@perf.compute_once
292284
def is_linearizable_concave(self) -> bool:
293285
"""Is the expression concave after linearizing all smooth subexpressions?
294286
"""
295287
# Applies DNLP composition rule.
296288
if self.is_constant():
297289
return True
298-
elif self.is_atom_smooth() or self.is_atom_nonsmooth_concave():
290+
elif self.is_atom_smooth() or self.is_atom_concave():
299291
for idx, arg in enumerate(self.args):
300292
if not (arg.is_smooth() or
301293
(arg.is_linearizable_concave() and self.is_incr(idx)) or

cvxpy/atoms/elementwise/abs.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,6 @@ def is_atom_concave(self) -> bool:
5555
"""Is the atom concave?
5656
"""
5757
return False
58-
59-
def is_atom_nonsmooth_convex(self) -> bool:
60-
"""Is the atom nonsmooth and convex?"""
61-
return True
6258

6359
def is_incr(self, idx) -> bool:
6460
"""Is the composition non-decreasing in argument idx?

cvxpy/atoms/elementwise/huber.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,6 @@ def is_atom_convex(self) -> bool:
7070
def is_atom_concave(self) -> bool:
7171
"""Is the atom concave?"""
7272
return False
73-
74-
def is_atom_nonsmooth_convex(self) -> bool:
75-
"""Is the atom nonsmooth and convex?"""
76-
return True
7773

7874
def is_incr(self, idx) -> bool:
7975
"""Is the composition non-decreasing in argument idx?"""

cvxpy/atoms/elementwise/maximum.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@ def is_atom_concave(self) -> bool:
6666
"""Is the atom concave?
6767
"""
6868
return False
69-
70-
def is_atom_nonsmooth_convex(self) -> bool:
71-
"""Is the atom nonsmooth and convex?"""
72-
return True
7369

7470
def is_atom_log_log_convex(self) -> bool:
7571
"""Is the atom log-log convex?

cvxpy/atoms/elementwise/minimum.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,6 @@ def is_atom_concave(self) -> bool:
5858
"""Is the atom concave?
5959
"""
6060
return True
61-
62-
def is_atom_nonsmooth_concave(self) -> bool:
63-
"""Is the atom nonsmooth and concave?"""
64-
return True
6561

6662
def is_atom_log_log_convex(self) -> bool:
6763
"""Is the atom log-log convex?

cvxpy/atoms/max.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,6 @@ def is_atom_concave(self) -> bool:
9999
"""Is the atom concave?
100100
"""
101101
return False
102-
103-
def is_atom_nonsmooth_convex(self) -> bool:
104-
"""Is the atom nonsmooth and convex?"""
105-
return True
106102

107103
def is_atom_log_log_convex(self) -> bool:
108104
"""Is the atom log-log convex?

cvxpy/atoms/min.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,6 @@ def is_atom_concave(self) -> bool:
9999
"""Is the atom concave?
100100
"""
101101
return True
102-
103-
def is_atom_nonsmooth_concave(self) -> bool:
104-
"""Is the atom nonsmooth and concave?"""
105-
return True
106102

107103
def is_atom_log_log_convex(self) -> bool:
108104
"""Is the atom log-log convex?

cvxpy/atoms/norm1.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,6 @@ def is_atom_concave(self) -> bool:
5555
"""Is the atom concave?
5656
"""
5757
return False
58-
59-
def is_atom_nonsmooth_convex(self) -> bool:
60-
"""Is the atom nonsmooth and convex?"""
61-
return True
6258

6359
def is_incr(self, idx) -> bool:
6460
"""Is the composition non-decreasing in argument idx?

cvxpy/atoms/norm_inf.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,6 @@ def is_atom_concave(self) -> bool:
5858
"""Is the atom concave?
5959
"""
6060
return False
61-
62-
def is_atom_nonsmooth_convex(self) -> bool:
63-
"""Is the atom nonsmooth and convex?"""
64-
return True
6561

6662
def is_atom_log_log_convex(self) -> bool:
6763
"""Is the atom log-log convex?

0 commit comments

Comments
 (0)