artofscience / SAOR

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

Upgrade `Poblem` class with wrapper function #28

Closed Giannis1993 closed 3 years ago

Giannis1993 commented 3 years ago

This is to discusss upgrading the abstract Problem class with a wrapper function that includes a method simulation(x). The previous discussions on that were the following:


@MaxvdKolk said:

Maybe @artofscience means that if there is a specific pattern for certain problems, for example to store/cache the solution of the simulation, we could provide a class that does something like that. Such that a user can implement only one function, that automatically deals with storing the solution/sensitivity as attribute and then returns whatever is needed when called through g, dg, ddg

class CachedProblem(Problem):
    def __init__(self, ...):
        # cached response/sensitivity 
        self.u, self.du = (None, None)

    def simulation(self, x):
        # perform simulation
        # this could also include a flag to indicate to simulation if it should
        # or should not evaluate the sensitivity/backward solutions
        self.u, self.du = solve_external_simulation(x)

    def g(self, x):
        # renew the simulation for `g`?
        self.simulation(x)
        return self.u

    def dg(self, x):
        # only renew simulation when sensitivity not present
        # otherwise just return whatever is present in the cache
        if not self.du:
            self.simulation(x)
        return self.du

Not sure if @artofscience hinted at this, but in this case we could make only simulation an abstract interface where the user needs to provide its call to solve the response and/or sensitivity based on a set of design variables

For an external user it would be

from sao.problems import CachedProblem

class MyCalculixProblem(CachedProblem):
    def simulation(self, x):
        # wrapper code goes here

@aatmdelissen said:

What is the exact purpose of the ddg method, if no explicit second derivatives are calculated? Does the abstract base-class provide default options for ddg? BFGS-kind of approximations?

The option @MaxvdKolk (CachedProblem) might be nice as a simple extension indeed, wrapping function-oriented code.

For the multiple-responses code, we might use something like

class MultiProblem(Problem):
    def __init__(self):
        self.problem[0] = Objective()
        self.problem[1] = Constraint()
        ...

    def g(self, x):
        u[:,0] = self.problem[0].g(x)
        u[:,1] = self.problem[1].g(x)
        ...
        return u

@Giannis1993 said:

@aatmdelissen There is no reason for ddg if it is not implemented, that's why it is not decorated with @abstractmethod in the class Problem(ABC). At a later stage however, we could indeed opt to place some BFGS-like scheme as a default option, if a 2nd-order Taylor expansion is chosen.

Giannis1993 commented 3 years ago

Problem class is defined