convexengineering / SPaircraft

Models for commercial aircraft design
http://spaircraft.readthedocs.org
25 stars 17 forks source link

sub for a vector variable? (and, fix documentation) #37

Closed mayork closed 7 years ago

mayork commented 7 years ago

@bqpd what's the proper way to do a substitution into a vectorized variable? I thought you could do something like

        if multimission:
               m.substitutions.update({
                    'n_{pax}': [180, 180, 120, 80]
                    })

but that doesn't appear to work. Didn't see any examples of this on the docs either.

bqpd commented 7 years ago

http://gpkit.readthedocs.io/en/latest/advancedcommands.html#substituting-multiple-values

Should work. Try seeing if it works on a posynomial but not on a model.

mayork commented 7 years ago

should that code run? because if I do a simple copy paste into my ipython i get this error

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-1-12d4389a6fbd> in <module>()
      5 p = x*y*z
      6 assert all(p.sub({x: 1, "y": 2}) == 2*z)
----> 7 assert all(p.sub({x: 1, y: 2, "z": [1, 2]}) == z.sub(z, [2, 4]))

/Users/mayork/Documents/GpGit/gpkit/gpkit/nomials/array.pyc in sub(self, subs, require_positive)
    147     def sub(self, subs, require_positive=True):
    148         "Substitutes into the array"
--> 149         return self.vectorize(lambda nom: nom.sub(subs, require_positive))
    150 
    151     @property

/Users/mayork/Documents/GpGit/gpkit/gpkit/nomials/array.pyc in vectorize(self, function, *args, **kwargs)
    131     def vectorize(self, function, *args, **kwargs):
    132         "Apply a function to each terminal constraint, returning the array"
--> 133         return vec_recurse(self, function, *args, **kwargs)
    134 
    135     __eq__ = array_constraint("=", eq)

/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/lib/function_base.pyc in __call__(self, *args, **kwargs)
   2216             vargs.extend([kwargs[_n] for _n in names])
   2217 
-> 2218         return self._vectorize_call(func=func, args=vargs)
   2219 
   2220     def _get_ufunc_and_otypes(self, func, args):

/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/lib/function_base.pyc in _vectorize_call(self, func, args)
   2279             _res = func()
   2280         else:
-> 2281             ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args)
   2282 
   2283             # Convert args to object arrays first

/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/lib/function_base.pyc in _get_ufunc_and_otypes(self, func, args)
   2241             # arrays (the input values are not checked to ensure this)
   2242             inputs = [asarray(_a).flat[0] for _a in args]
-> 2243             outputs = func(*inputs)
   2244 
   2245             # Performance note: profiling indicates that -- for simple

/Users/mayork/Documents/GpGit/gpkit/gpkit/nomials/array.pyc in vec_recurse(element, function, *args, **kwargs)
     23 def vec_recurse(element, function, *args, **kwargs):
     24     "Vectorizes function with particular args and kwargs"
---> 25     return function(element, *args, **kwargs)
     26 
     27 

/Users/mayork/Documents/GpGit/gpkit/gpkit/nomials/array.pyc in <lambda>(nom)
    147     def sub(self, subs, require_positive=True):
    148         "Substitutes into the array"
--> 149         return self.vectorize(lambda nom: nom.sub(subs, require_positive))
    150 
    151     @property

/Users/mayork/Documents/GpGit/gpkit/gpkit/nomials/variables.pyc in sub(self, *args, **kwargs)
     85             if not isinstance(arg, dict):
     86                 args = ({self: arg},)
---> 87         return Monomial.sub(self, *args, **kwargs)
     88 
     89 

/Users/mayork/Documents/GpGit/gpkit/gpkit/nomials/nomial_math.pyc in sub(self, substitutions, require_positive)
    217         Returns substituted nomial.
    218         """
--> 219         _, exps, cs, _ = substitution(self, substitutions)
    220         return Signomial(exps, cs, require_positive=require_positive)
    221 

/Users/mayork/Documents/GpGit/gpkit/gpkit/nomials/substitution.pyc in substitution(nomial, substitutions)
    108         return nomial.varlocs, nomial.exps, nomial.cs, substitutions
    109 
--> 110     subs, _, _ = parse_subs(nomial.varkeys, substitutions)
    111 
    112     if not subs:

/Users/mayork/Documents/GpGit/gpkit/gpkit/nomials/substitution.pyc in parse_subs(varkeys, substitutions)
     26             key = getattr(var, "key", var)
     27             if key in varkeys.keymap:
---> 28                 sub, keys = substitutions[var], varkeys.keymap[key]
     29                 append_sub(sub, keys, constants, sweep, linkedsweep)
     30     return constants, sweep, linkedsweep

IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices
bqpd commented 7 years ago

That exact code is in a unit test. Does your install pass all unit tests?

mayork commented 7 years ago

weird....i pass all the unit tests, just checked

bqpd commented 7 years ago

Oh wait nvm there's a small but crucial difference:

x = Variable("x")
y = Variable("y")
z = VectorVariable(2, "z")
p = x*y*z
assert all(p.sub({x: 1, "y": 2}) == 2*z)
assert all(p.sub({x: 1, y: 2, "z": [1, 2]}) ==  z.sub({z: [2, 4]}))
bqpd commented 7 years ago

The z, [2, 4] is what was causing the documented code to not work.

mayork commented 7 years ago

is there a way we can make the code i originally posted work? I'd rather not do a sub into a posynomial on the D8 model

bqpd commented 7 years ago

That seems like it should work, as it follows the test, so this may be a model/posynomial substitution distinction. Could you try seeing if it works on a posynomial but not on a model?

mayork commented 7 years ago

it is model vs posynomial. the following works

        p = x * ReqRng
        p.sub({x: 1, "ReqRng": [3000, 3100]}) 
mayork commented 7 years ago

@bqpd was there any updates on this?

mayork commented 7 years ago

@bqpd bump...our code is getting quite complex and getting this working right could really simplify some things

bqpd commented 7 years ago

looking into it...surprise surprise it only happens with SPs

bqpd commented 7 years ago

got it. only happens when you use 1) lists and 2) SPs. good times. fixed in the PR above for my test case, try it