convexengineering / gpkit

Geometric programming for engineers
http://gpkit.readthedocs.org
MIT License
206 stars 40 forks source link

Call external solver during SP solve #590

Closed bqpd closed 8 years ago

bqpd commented 8 years ago

These should be tested, written, used:

For changing a constant:

import numpy as np
from gpkit.constraint.set import ConstraintSet

class ChangeConstantConstraint(ConstraintSet):

    def as_gpconstr(self, x0):
        gpconstr = super(ConstraintSet, self).as_gpconstr(x0)
        if x0["Re"] >= 1e6:
            gpconstr.substitution.update(xfoil(x0))
        return gpconstr

def xfoil(x0):
    return {"CD": np.sin(x0["Re"])}

For inserting a constraint:


def xfoil(x0):
    return [PosynomialInequality, MonomialEquality]

class ChangeConstantConstraint(ConstraintSet):

    def as_gpconstr(self, x0):
        gpconstr = super(ConstraintSet, self).as_gpconstr(x0)
        if x0["Re"] >= 1e6:
            constraints = xfoil(x0)
        else:
            constraints = [PosynomialInequality, MonomialEquality]
        return ConstraintSet([gpconstr, constraints])
bqpd commented 8 years ago

Alternative conditions for calling the outside function, besides variable bounds include

codykarcher commented 8 years ago

What file should these things live in?

bqpd commented 8 years ago

These should live in one of your code files, where they can reference variables and so on. You can wrap all your other constraints in one of these (for the substitutions one) or just the relevant constraints (for the "add a bonus constraint" one).

codykarcher commented 8 years ago

I just pulled, but I have no module named constraint? Not sure what's going on here. I also can't find ConstraintSet in the source code...

codykarcher commented 8 years ago

Here's a MWE we can reference:

from gpkit import VectorVariable, Variable, Model, units
import gpkit
from gpkit.constraint import ConstraintSet

Re = Variable("Re", 1e7, "-", "Reynolds Number")
CL = Variable("C_L", 1.0, "-", "Lift Coefficient")
CD = Variable("C_D", "-", "Drag Coefficient")

def xfoil(x0):
    return [CD >= 0.01 + .03*CL**2]

class AeroModel(ConstraintSet):

    def as_gpconstr(self, x0):
        gpconstr = super(ConstraintSet, self).as_gpconstr(x0)
        if x0["Re"] >= 1e6:
            constraints = xfoil(x0)
        else:
            constraints = [CD >= 1. + CL**2]
        return ConstraintSet([gpconstr, constraints])

constraints = AeroModel.as_gpconstr([])

objective = CD

m = Model(objective, constraints)
m.solve('cvxopt', verbosity=1)

Should return CD=0.04 in its current state and CD=2.0 when we drop the Re beneath the cutoff. Pretty convinced this is not how it was intended to be implemented, but it's my best guess.

bqpd commented 8 years ago

Great example. Updated and working on my computer on the "externalsolver" branch:

from gpkit import VectorVariable, Variable, units, SignomialProgram
import gpkit
from gpkit.constraints.set import ConstraintSet

Re = Variable("Re", "-", "Reynolds Number")
CL = Variable("C_L", "-", "Lift Coefficient")
CD = Variable("C_D", "-", "Drag Coefficient")

def xfoil(x0):
    return [CD >= 0.01 + .03*CL**2]

class AeroModel(ConstraintSet):

    def as_gpconstr(self, x0):
        gpconstr = super(AeroModel, self).as_gpconstr(x0)
        if x0 and x0["Re"] >= 1e6:
            constraints = xfoil(x0)
        else:
            constraints = [CD >= 1. + CL**2]
        return ConstraintSet([gpconstr, constraints])

constraints = AeroModel([CL >= 1.0, Re == 1e7])

objective = CD

m = SignomialProgram(objective, constraints, require_signomial=False)
m.localsolve('cvxopt', verbosity=1)
codykarcher commented 8 years ago

Works for me now too. I'm going to close and raise new issues as they come up. Thanks @bqpd

codykarcher commented 8 years ago

nvm, I can't close the issue... @whoburg

whoburg commented 8 years ago

Looking great. Exciting that we can do this so cleanly.

Remaining todos:

whoburg commented 8 years ago

shall we close this now that @cjk12 implemented #687 ?

bqpd commented 8 years ago

Looks great! http://gpkit.readthedocs.org/en/latest/signomialprogramming.html#calling-to-external-codes