support functions (transform, and atom)#860
Conversation
|
Very cool! Will take a closer soon. (Also, thanks for fixing the MOSEK interface.) Just one comment for now.
Actually, the first argument to |
Wonderful news! I will change the implementation to reflect that. Although, this now raises a question for me: what is the purpose of the second argument to |
|
Okay, now that the hack with suppfunc_canon is fixed, I think this PR is in much better shape. Here are some points to consider in the review:
One consistent thought I had throughout this process, is that it would be very useful if convex sets were first-class objects within cvxpy. If you'd like to discuss this more, let me know. |
The args passed to a canon method are canonicalized args, ie, they are affine expressions representing the epigraph variables for the args. You’re right that the semantics of these arguments should be documented. You can look at the Canonicalization reduction to see what exactly is passed to canonicalizers. This is a really cool change! I agree with / am okay with all of your three points. |
|
@rileyjmurray can you say more about what you mean by convex sets are not first class objects? I added an Indicator transform at one point to convert constraints to atoms of the form [edit] I guess what I mean is that I view constraints as the current implementation of convex sets. Anyway this is a very cool PR! It would be great to have examples of the different operations you mentioned. |
|
@SteveDiamond Constraint objects completely handle the problem of membership in a set. However, in convex analysis, we often want to do more than just enforce membership. We want to transform sets, and build more complicated sets from simpler sets. Common operations include applying a linear operator, taking set-intersection, or computing a Cartesian product. Less-common (but still fundamental) operations include taking Minkowski sums, polar bodies, conic hulls, or dual cones. Most of these operations have some implementation in terms of Constraint objects (or using the There are different ways that a ConvexSet class could be introduced. In one scenario, ConvexSet objects are only used in the background, as a way to facilitate more complicated transforms I've described above. In another scenario, ConvexSet objects could be exposed to the user. I think there are compelling mathematical and performance reasons to expose a ConvexSet class to users. I give one performance reason below. A possible (end-user) use-case of a ConvexSet class.Consider a scenario where a user has a repeated constraint pattern they want to apply to every expression in a long Right now, a user can do this in a clean way defining a function The downside to that approach, is that cvxpy has no idea that so many of the constraint objects are just slight variations on one another. Now consider the same scenario where the user has a ConvexSet class at their disposal. They would simply construct the convex set If each of the Constraint objects |
|
@SteveDiamond as to examples, let me know if I need to add some in order to get this PR merged. There are several tests which could be converted into examples without too much trouble. |
|
@rileyjmurray no need, it looks good. Your comments on convex sets as a first class object were very clarifying. |
Checked out from rileyjmurray's PR (#860)
Checked out from rileyjmurray's PR (#860)
|
@SteveDiamond I've resolved your comments. Should be ready to merge, assuming @akshayka doesn't want to make additional comments. |
|
Looks good! I merged it in. |
This PR focuses on the content of my accidental merge from earlier today. It also contains fixes to the MOSEK interface.
Users can get a handle on a
SuppFuncobject by callingsigma = cvxpy.suppfunc(x, constrs). From there,SuppFuncAtomobjects are generated by evaluating theSuppFuncobject. So a user could writesigma(y) <= 1, and this generates aSuppFuncAtomobject and a cvxpy inequality constraint in the same line of code.It may seem odd to have two separate classes for this feature. This is necessary because cvxpy doesn't consider convex sets as first-class objects. After quite a bit of thinking, I think the best way to represent a convex set in cvxpy is with a pair
(expr, constrs), where this pair stands in forS = {val : constraints in constrs can be satisfied, when expr.value = val}.From an implementation perspective, I also need to map an
(expr, constrs)pair into a conic formS = {x : A @ [x, y] + b in K }. I did this by having theSuppFuncclass execute a call toget_problem_data(solver='SCS'), and then reaching slightly back into the solver reduction chain. Due to the nature of this approach, I can't cleanly construct all the convex sets I'd really like to. The current implementation only allows sets(x, constrs)wherexis a cvxpy Variable with no special attributes (i.e. no declared symmetry, nonnegativity, etc...). This isn't a huge limitation, but it's certainly worth mentioning.The one thing I don't like about this implementation is how
SuppFuncAtomobjects maintain some of their metadata. When one of these objects is constructed, I stash an extra dictionary inside the__dict__field of an existingcvxpy.Constantobject. I do this because thesuppfunc_canonfunction defined within thedcp2conefolder doesn't have access to theSuppFuncAtomobject in question; it only has access to theargsfield of thatSuppFuncAtomobject! I tried storing all necessary data in theargsfield ofSuppFuncAtomobjects, but it seems that strong assumptions are placed on the elements ofargselsewhere in the compilation process. I don't know how to pass the necessary data through objects that satisfy the (unwritten?) assumptions onargs, so for now I have this hacky solution.