artofscience / SAOR

Sequential Approximate Optimization Repository
GNU General Public License v3.0
5 stars 1 forks source link

Implement feature to warn about non-convexity #63

Open MaxvdKolk opened 3 years ago

MaxvdKolk commented 3 years ago

It might be nice to try and implement the convexity enforcement as a separate (wrapper) class. At the moment, it seems that we would need to implement the if self.force_convex check, as well as the corresponding enforce_convexity routines for various instances of the Approximation classes. Additionally, there might be different approaches possible in which we would like to enforce convexity. For instance, we could consider other thresholds or values to assign to the second derivatives.

My proposal would be to implement something as follows

class EnforceConvexity(Approximation):
    def __init__(self, approximation: Approximation, convexity_enforcer: Callable):
        self.approximation = approximation
        self.enforcer = convexity_enforcer

    def update(self, ...):
        self.approximation.update(self, ...)
        self.enforcer(self.approximation)

which would sit around an existing Approximation instance, so initialised as approximation = EnforceConvexity(Approximation(...), convexity_enforcer), where the convexity_enforcer could be any function (or class) that takes the approximation as argument

def convexity_enforcer_1(approximation):
    for intv in range(len(approximation.ddgddy):
        approximation.ddgddy[intv][approximation.ddgddy[intv] < 0] = 0

for which we could implement a couple different variants. With such a (or similar) scheme, we could potentially then provide a range of such enforce_convexity routines that could work on any Approximation without requiring to modify the update method of the Approximation classes directly.


There are of course multiple ways to implement behaviour like this and possibly we should consider a PR/issue for this to see what would be the most appropriate way to insert this into the framework.

_Originally posted by @MaxvdKolk in https://github.com/artofscience/sao/pull/62#discussion_r657285997_

artofscience commented 3 years ago

To get a good view let us discuss the different types of enforcing convexity

MaxvdKolk commented 3 years ago

Agree, would be nice to see if most common methods can be implemented with a simple function or that we might want to think about putting this into more detailed classes etc.

Giannis1993 commented 3 years ago

This is a bit tricky to implement for the 2nd-order Taylor expansions with respect to an arbitrary intervening variable y. The reason being that we must enforce the convexity of \tilde{g}[y[x]] wrt to x and not y. Equations become quite complex, so we might want to leave it out for now. Perhaps we can implement it only on the 1st-order methods and warn the user for the 2nd-order ones or something.

Giannis1993 commented 3 years ago

After looking into this and discussing with @artofscience, we concluded that a realistic and viable option would be to implement a method in the Approximation class that will warn the user when entries of subprob.ddg(x) and therefore entries of approx.ddg(x) become negative. That way we are consistent in handling non-convexity throughout the package, cuz enforcing convexity in the case of an arbitrary intervening variable y[x] in combination with any of our Taylor2 expansion proved to be pretty hard to solve.

artofscience commented 2 years ago

Why not add some functions to the "subproblem" object: e.g.

  1. Check convexity
  2. Check separability
  3. etc. Since those properties not only depend on the approximation, but also on the move limits etc.