From f7f5c4ae9cfeddce07c792b97ed3dec81e516d83 Mon Sep 17 00:00:00 2001 From: Edward Burnell Date: Thu, 4 Aug 2016 07:09:05 -0700 Subject: [PATCH 01/12] don't autogenerate varkeys --- docs/source/examples/beam.py | 2 ++ gpkit/constraints/costed.py | 5 ++--- gpkit/constraints/linked.py | 4 ++++ gpkit/constraints/model.py | 1 + gpkit/constraints/set.py | 18 +++++++----------- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/docs/source/examples/beam.py b/docs/source/examples/beam.py index 522b2175e..7cd0212b5 100644 --- a/docs/source/examples/beam.py +++ b/docs/source/examples/beam.py @@ -47,6 +47,8 @@ def __init__(self, N=4, **kwargs): theta_eq[0] = (th[0] >= th_base) # base boundary condition displ_eq = (w >= w.left + 0.5*dx*(th + th.left)) displ_eq[0] = (w[0] >= w_base) + for constraint in [shear_eq, moment_eq, theta_eq, displ_eq]: + constraint.update_varkeys() # minimize tip displacement (the last w) Model.__init__(self, w[-1], [shear_eq, moment_eq, theta_eq, displ_eq, diff --git a/gpkit/constraints/costed.py b/gpkit/constraints/costed.py index 09f93a3e9..c4afc0afa 100644 --- a/gpkit/constraints/costed.py +++ b/gpkit/constraints/costed.py @@ -24,10 +24,9 @@ def subinplace(self, subs): self.cost = self.cost.sub(subs) ConstraintSet.subinplace(self, subs) - @property - def varkeys(self): + def update_varkeys(self): "return all Varkeys present in this ConstraintSet" - return ConstraintSet._varkeys(self, self.cost.varlocs) + ConstraintSet.update_varkeys(self, self.cost.varlocs) def rootconstr_str(self, excluded=None): "The appearance of a ConstraintSet in addition to its contents" diff --git a/gpkit/constraints/linked.py b/gpkit/constraints/linked.py index 340bc461e..31189919a 100644 --- a/gpkit/constraints/linked.py +++ b/gpkit/constraints/linked.py @@ -66,6 +66,10 @@ def __init__(self, constraints, include_only=None, exclude=None): self.reverselinks[newvk] = vks with SignomialsEnabled(): # since we're just substituting varkeys. self.subinplace(self.linked) + for constraint in self: + if hasattr(constraint, "update_varkeys"): + constraint.update_varkeys() + self.update_varkeys() def process_result(self, result): super(LinkedConstraintSet, self).process_result(result) diff --git a/gpkit/constraints/model.py b/gpkit/constraints/model.py index b8f7ff726..882c1258b 100644 --- a/gpkit/constraints/model.py +++ b/gpkit/constraints/model.py @@ -98,6 +98,7 @@ def _add_modelname_tovars(self, name, num): del self.substitutions[vk] with SignomialsEnabled(): # since we're just substituting varkeys. self.subinplace(add_model_subs) + self.update_varkeys() def subconstr_str(self, excluded=None): "The collapsed appearance of a ConstraintBase" diff --git a/gpkit/constraints/set.py b/gpkit/constraints/set.py index 83d72cc88..49407d1ad 100644 --- a/gpkit/constraints/set.py +++ b/gpkit/constraints/set.py @@ -28,6 +28,7 @@ def __init__(self, constraints, substitutions=None, recursesubs=True): # grab the substitutions dict from the top constraintset subs.update(constraints.substitutions) # pylint: disable=no-member if recursesubs: + self.update_varkeys() self.substitutions = KeyDict.with_keys(self.varkeys, self._iter_subs(subs)) else: @@ -127,19 +128,14 @@ def subinplace(self, subs): for constraint in self: constraint.subinplace(subs) - @property - def varkeys(self): - "return all Varkeys present in this ConstraintSet" - return self._varkeys() - - def _varkeys(self, init_dict=None): - "return all Varkeys present in this ConstraintSet" - init_dict = {} if init_dict is None else init_dict - out = KeySet(init_dict) + def update_varkeys(self, init_dict={}): + varkeys = KeySet(init_dict) for constraint in self: if hasattr(constraint, "varkeys"): - out.update(constraint.varkeys) - return out + varkeys.update(constraint.varkeys) + # else: + # print type(constraint) # getting numpy bools... + self.varkeys = varkeys def as_posyslt1(self): "Returns list of posynomials which must be kept <= 1" From 5158ec48112c7f7f3c3b3334f56c54f3f10cf725 Mon Sep 17 00:00:00 2001 From: Edward Burnell Date: Thu, 4 Aug 2016 07:14:58 -0700 Subject: [PATCH 02/12] make it easy to add varkeys --- gpkit/keydict.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gpkit/keydict.py b/gpkit/keydict.py index aba2fe594..41018fc46 100644 --- a/gpkit/keydict.py +++ b/gpkit/keydict.py @@ -42,6 +42,10 @@ def __init__(self, *args, **kwargs): self.keymap = defaultdict(set) self.update(*args, **kwargs) + def add(self, *args): + for arg in args: + self[arg] = None + def update(self, *args, **kwargs): "Iterates through the dictionary created by args and kwargs" for k, v in dict(*args, **kwargs).items(): From 66c588b6e8dac575f475247ce6b150e7a076cc8b Mon Sep 17 00:00:00 2001 From: Edward Burnell Date: Thu, 4 Aug 2016 07:46:23 -0700 Subject: [PATCH 03/12] lint and rename --- docs/source/examples/beam.py | 2 +- gpkit/constraints/costed.py | 7 +++++-- gpkit/constraints/linked.py | 13 ++++++------- gpkit/constraints/model.py | 2 +- gpkit/constraints/prog_factories.py | 9 +++++---- gpkit/constraints/set.py | 9 ++++++--- gpkit/keydict.py | 9 +++++---- 7 files changed, 29 insertions(+), 22 deletions(-) diff --git a/docs/source/examples/beam.py b/docs/source/examples/beam.py index 7cd0212b5..2af7f670c 100644 --- a/docs/source/examples/beam.py +++ b/docs/source/examples/beam.py @@ -48,7 +48,7 @@ def __init__(self, N=4, **kwargs): displ_eq = (w >= w.left + 0.5*dx*(th + th.left)) displ_eq[0] = (w[0] >= w_base) for constraint in [shear_eq, moment_eq, theta_eq, displ_eq]: - constraint.update_varkeys() + constraint.reset_varkeys() # minimize tip displacement (the last w) Model.__init__(self, w[-1], [shear_eq, moment_eq, theta_eq, displ_eq, diff --git a/gpkit/constraints/costed.py b/gpkit/constraints/costed.py index c4afc0afa..2a7750aab 100644 --- a/gpkit/constraints/costed.py +++ b/gpkit/constraints/costed.py @@ -24,9 +24,12 @@ def subinplace(self, subs): self.cost = self.cost.sub(subs) ConstraintSet.subinplace(self, subs) - def update_varkeys(self): + def reset_varkeys(self, init_dict=None): "return all Varkeys present in this ConstraintSet" - ConstraintSet.update_varkeys(self, self.cost.varlocs) + costkeys = dict(self.cost.varlocs) + if init_dict is not None: + costkeys.update(init_dict) + ConstraintSet.reset_varkeys(self, costkeys) def rootconstr_str(self, excluded=None): "The appearance of a ConstraintSet in addition to its contents" diff --git a/gpkit/constraints/linked.py b/gpkit/constraints/linked.py index 31189919a..d9b1d9c29 100644 --- a/gpkit/constraints/linked.py +++ b/gpkit/constraints/linked.py @@ -27,11 +27,10 @@ class LinkedConstraintSet(ConstraintSet): """ def __init__(self, constraints, include_only=None, exclude=None): ConstraintSet.__init__(self, constraints) - varkeys = self.varkeys linkable = set() - for varkey in varkeys: + for varkey in self.varkeys: name_without_model = varkey.str_without(["models"]) - if len(varkeys[name_without_model]) > 1: + if len(self.varkeys[name_without_model]) > 1: linkable.add(name_without_model) if include_only: linkable &= set(include_only) @@ -39,7 +38,7 @@ def __init__(self, constraints, include_only=None, exclude=None): linkable -= set(exclude) self.linked, self.reverselinks = {}, {} for name in linkable: - vks = varkeys[name] + vks = self.varkeys[name] sub, subbed_vk = None, None for vk in vks: if vk in self.substitutions: @@ -67,9 +66,9 @@ def __init__(self, constraints, include_only=None, exclude=None): with SignomialsEnabled(): # since we're just substituting varkeys. self.subinplace(self.linked) for constraint in self: - if hasattr(constraint, "update_varkeys"): - constraint.update_varkeys() - self.update_varkeys() + if hasattr(constraint, "reset_varkeys"): + constraint.reset_varkeys() + self.reset_varkeys() def process_result(self, result): super(LinkedConstraintSet, self).process_result(result) diff --git a/gpkit/constraints/model.py b/gpkit/constraints/model.py index 882c1258b..2104ab90c 100644 --- a/gpkit/constraints/model.py +++ b/gpkit/constraints/model.py @@ -98,7 +98,7 @@ def _add_modelname_tovars(self, name, num): del self.substitutions[vk] with SignomialsEnabled(): # since we're just substituting varkeys. self.subinplace(add_model_subs) - self.update_varkeys() + self.reset_varkeys() def subconstr_str(self, excluded=None): "The collapsed appearance of a ConstraintBase" diff --git a/gpkit/constraints/prog_factories.py b/gpkit/constraints/prog_factories.py index 01e89fc1c..2cc599af7 100644 --- a/gpkit/constraints/prog_factories.py +++ b/gpkit/constraints/prog_factories.py @@ -1,10 +1,6 @@ "Scripts for generating, solving and sweeping programs" from time import time import numpy as np -from ..nomials.substitution import parse_subs -from ..solution_array import SolutionArray -from ..keydict import KeyDict -from ..varkey import VarKey try: from ipyparallel import Client @@ -16,6 +12,11 @@ except (ImportError, IOError, AssertionError): POOL = None +from ..nomials.substitution import parse_subs +from ..solution_array import SolutionArray +from ..keydict import KeyDict +from ..varkey import VarKey + def _progify_fctry(program, return_attr=None): "Generates function that returns a program() and optionally an attribute." diff --git a/gpkit/constraints/set.py b/gpkit/constraints/set.py index 49407d1ad..22f9fe5a2 100644 --- a/gpkit/constraints/set.py +++ b/gpkit/constraints/set.py @@ -28,7 +28,7 @@ def __init__(self, constraints, substitutions=None, recursesubs=True): # grab the substitutions dict from the top constraintset subs.update(constraints.substitutions) # pylint: disable=no-member if recursesubs: - self.update_varkeys() + self.reset_varkeys() self.substitutions = KeyDict.with_keys(self.varkeys, self._iter_subs(subs)) else: @@ -128,8 +128,11 @@ def subinplace(self, subs): for constraint in self: constraint.subinplace(subs) - def update_varkeys(self, init_dict={}): - varkeys = KeySet(init_dict) + def reset_varkeys(self, init_dict=None): + "Goes through constraints and collects their varkeys." + varkeys = KeySet() + if not init_dict is None: + varkeys.update(init_dict) for constraint in self: if hasattr(constraint, "varkeys"): varkeys.update(constraint.varkeys) diff --git a/gpkit/keydict.py b/gpkit/keydict.py index 41018fc46..e6245aa50 100644 --- a/gpkit/keydict.py +++ b/gpkit/keydict.py @@ -42,10 +42,6 @@ def __init__(self, *args, **kwargs): self.keymap = defaultdict(set) self.update(*args, **kwargs) - def add(self, *args): - for arg in args: - self[arg] = None - def update(self, *args, **kwargs): "Iterates through the dictionary created by args and kwargs" for k, v in dict(*args, **kwargs).items(): @@ -153,6 +149,11 @@ class KeySet(KeyDict): "KeySets are KeyDicts without values, serving only to filter and map keys" collapse_arrays = False + def add(self, *args): + "Adds all args to the keyset" + for arg in args: + self[arg] = None + def __getitem__(self, key): "Gets the keys corresponding to a particular key." key, _ = self.parse_and_index(key) From 32410c4d758f71ec244558ae14d86d0549bc749e Mon Sep 17 00:00:00 2001 From: Edward Burnell Date: Thu, 4 Aug 2016 09:10:31 -0700 Subject: [PATCH 04/12] implement set syntax --- gpkit/keydict.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/gpkit/keydict.py b/gpkit/keydict.py index e6245aa50..f45bbb695 100644 --- a/gpkit/keydict.py +++ b/gpkit/keydict.py @@ -149,10 +149,14 @@ class KeySet(KeyDict): "KeySets are KeyDicts without values, serving only to filter and map keys" collapse_arrays = False - def add(self, *args): - "Adds all args to the keyset" - for arg in args: - self[arg] = None + def add(self, item): + "Adds an item to the keyset" + self[item] = None + + def union(self, iterable): + "Adds an iterable to the keyset" + for item in iterable: + self.add(item) def __getitem__(self, key): "Gets the keys corresponding to a particular key." From 236dacbd4268c5917aab6646d77510ad6ae33aa1 Mon Sep 17 00:00:00 2001 From: Edward Burnell Date: Thu, 4 Aug 2016 09:15:09 -0700 Subject: [PATCH 05/12] response to code review (docstring and beam fix) --- docs/source/examples/beam.py | 6 +++-- docs/source/examples/beam_output.txt | 33 ---------------------------- gpkit/constraints/costed.py | 2 +- 3 files changed, 5 insertions(+), 36 deletions(-) diff --git a/docs/source/examples/beam.py b/docs/source/examples/beam.py index 2af7f670c..0af28a7d8 100644 --- a/docs/source/examples/beam.py +++ b/docs/source/examples/beam.py @@ -40,15 +40,17 @@ def __init__(self, N=4, **kwargs): # shear and moment increase from tip to base (left > right) shear_eq = (V >= V.right + 0.5*dx*(q + q.right)) shear_eq[-1] = (V[-1] >= V_tip) # tip boundary condition + shear_eq.varkeys.add(V_tip) moment_eq = (M >= M.right + 0.5*dx*(V + V.right)) moment_eq[-1] = (M[-1] >= M_tip) + moment_eq.varkeys.add(M_tip) # slope and displacement increase from base to tip (right > left) theta_eq = (th >= th.left + 0.5*dx*(M + M.left)/EI) theta_eq[0] = (th[0] >= th_base) # base boundary condition + theta_eq.varkeys.add(th_base) displ_eq = (w >= w.left + 0.5*dx*(th + th.left)) displ_eq[0] = (w[0] >= w_base) - for constraint in [shear_eq, moment_eq, theta_eq, displ_eq]: - constraint.reset_varkeys() + displ_eq.varkeys.add(w_base) # minimize tip displacement (the last w) Model.__init__(self, w[-1], [shear_eq, moment_eq, theta_eq, displ_eq, diff --git a/docs/source/examples/beam_output.txt b/docs/source/examples/beam_output.txt index b49476155..e69de29bb 100644 --- a/docs/source/examples/beam_output.txt +++ b/docs/source/examples/beam_output.txt @@ -1,33 +0,0 @@ - -Cost ----- - 1.62 [m] - -Free Variables --------------- - dx : 1.2 [m] Length of an element - \vec{M} : [ 1.98e+03 1.27e+03 713 317 ... ] [N*m] Internal moment - \vec{V} : [ 660 528 396 264 ... ] [N] Internal shear -\vec{\theta} : [ - 0.177 0.285 0.341 ... ] Slope - \vec{w} : [ - 0.106 0.384 0.759 ... ] [m] Displacement - -Constants ---------- - EI : 1.1e+04 [N*m**2] - L : 6 [m] Overall beam length - M_{tip} : 0 [N*m] Tip moment - V_{tip} : 0 [N] Tip loading -\theta_{base} : 0 Base angle - w_{base} : 0 [m] Base deflection - \vec{M} : [ - - - - ... ] [N*m] Internal moment - \vec{V} : [ - - - - ... ] [N] Internal shear - \vec{\theta} : [ 0 - - - ... ] Slope - \vec{q} : [ 110 110 110 110 ... ] [N/m] Distributed load at each point - \vec{w} : [ 0 - - - ... ] [m] Displacement - -Sensitivities -------------- - L : 4 Overall beam length -\vec{q} : [ 0.0072 0.0416 0.118 0.234 ... ] Distributed load at each point - EI : -1 - diff --git a/gpkit/constraints/costed.py b/gpkit/constraints/costed.py index 2a7750aab..43fb114d6 100644 --- a/gpkit/constraints/costed.py +++ b/gpkit/constraints/costed.py @@ -25,7 +25,7 @@ def subinplace(self, subs): ConstraintSet.subinplace(self, subs) def reset_varkeys(self, init_dict=None): - "return all Varkeys present in this ConstraintSet" + "Resets varkeys to what is in the cost and constraints" costkeys = dict(self.cost.varlocs) if init_dict is not None: costkeys.update(init_dict) From f5994530722bb29ce95b454afbb9c3a94c1b83b3 Mon Sep 17 00:00:00 2001 From: Edward Burnell Date: Thu, 4 Aug 2016 12:59:58 -0700 Subject: [PATCH 06/12] fix named unused variables --- gpkit/constraints/costed.py | 13 ++++++++++--- gpkit/constraints/set.py | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/gpkit/constraints/costed.py b/gpkit/constraints/costed.py index 43fb114d6..517dc062b 100644 --- a/gpkit/constraints/costed.py +++ b/gpkit/constraints/costed.py @@ -22,14 +22,21 @@ def __init__(self, cost, constraints, substitutions=None): def subinplace(self, subs): "Substitutes in place." self.cost = self.cost.sub(subs) + if hasattr(self, "unused_variables"): + unused_vars = [] + for var in self.unused_variables: + if var.key in subs: + unused_vars.append(subs[var.key]) + else: + unused_vars.append(var.key) + self.unused_variables = unused_vars ConstraintSet.subinplace(self, subs) def reset_varkeys(self, init_dict=None): "Resets varkeys to what is in the cost and constraints" - costkeys = dict(self.cost.varlocs) + ConstraintSet.reset_varkeys(self, self.cost.varlocs) if init_dict is not None: - costkeys.update(init_dict) - ConstraintSet.reset_varkeys(self, costkeys) + self.varkeys.union(init_dict) def rootconstr_str(self, excluded=None): "The appearance of a ConstraintSet in addition to its contents" diff --git a/gpkit/constraints/set.py b/gpkit/constraints/set.py index 22f9fe5a2..3aca6b51a 100644 --- a/gpkit/constraints/set.py +++ b/gpkit/constraints/set.py @@ -136,8 +136,8 @@ def reset_varkeys(self, init_dict=None): for constraint in self: if hasattr(constraint, "varkeys"): varkeys.update(constraint.varkeys) - # else: - # print type(constraint) # getting numpy bools... + if hasattr(self, "unused_variables"): + varkeys.union(self.unused_variables) self.varkeys = varkeys def as_posyslt1(self): From 76dd54f0c3f1f83a638d8df22a2a24c2c09186bc Mon Sep 17 00:00:00 2001 From: Edward Burnell Date: Thu, 4 Aug 2016 13:26:31 -0700 Subject: [PATCH 07/12] reset varkeys on setitem --- docs/source/examples/beam.py | 4 ---- docs/source/examples/beam_output.txt | 33 ++++++++++++++++++++++++++++ gpkit/constraints/set.py | 4 ++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/docs/source/examples/beam.py b/docs/source/examples/beam.py index 0af28a7d8..522b2175e 100644 --- a/docs/source/examples/beam.py +++ b/docs/source/examples/beam.py @@ -40,17 +40,13 @@ def __init__(self, N=4, **kwargs): # shear and moment increase from tip to base (left > right) shear_eq = (V >= V.right + 0.5*dx*(q + q.right)) shear_eq[-1] = (V[-1] >= V_tip) # tip boundary condition - shear_eq.varkeys.add(V_tip) moment_eq = (M >= M.right + 0.5*dx*(V + V.right)) moment_eq[-1] = (M[-1] >= M_tip) - moment_eq.varkeys.add(M_tip) # slope and displacement increase from base to tip (right > left) theta_eq = (th >= th.left + 0.5*dx*(M + M.left)/EI) theta_eq[0] = (th[0] >= th_base) # base boundary condition - theta_eq.varkeys.add(th_base) displ_eq = (w >= w.left + 0.5*dx*(th + th.left)) displ_eq[0] = (w[0] >= w_base) - displ_eq.varkeys.add(w_base) # minimize tip displacement (the last w) Model.__init__(self, w[-1], [shear_eq, moment_eq, theta_eq, displ_eq, diff --git a/docs/source/examples/beam_output.txt b/docs/source/examples/beam_output.txt index e69de29bb..b49476155 100644 --- a/docs/source/examples/beam_output.txt +++ b/docs/source/examples/beam_output.txt @@ -0,0 +1,33 @@ + +Cost +---- + 1.62 [m] + +Free Variables +-------------- + dx : 1.2 [m] Length of an element + \vec{M} : [ 1.98e+03 1.27e+03 713 317 ... ] [N*m] Internal moment + \vec{V} : [ 660 528 396 264 ... ] [N] Internal shear +\vec{\theta} : [ - 0.177 0.285 0.341 ... ] Slope + \vec{w} : [ - 0.106 0.384 0.759 ... ] [m] Displacement + +Constants +--------- + EI : 1.1e+04 [N*m**2] + L : 6 [m] Overall beam length + M_{tip} : 0 [N*m] Tip moment + V_{tip} : 0 [N] Tip loading +\theta_{base} : 0 Base angle + w_{base} : 0 [m] Base deflection + \vec{M} : [ - - - - ... ] [N*m] Internal moment + \vec{V} : [ - - - - ... ] [N] Internal shear + \vec{\theta} : [ 0 - - - ... ] Slope + \vec{q} : [ 110 110 110 110 ... ] [N/m] Distributed load at each point + \vec{w} : [ 0 - - - ... ] [m] Displacement + +Sensitivities +------------- + L : 4 Overall beam length +\vec{q} : [ 0.0072 0.0416 0.118 0.234 ... ] Distributed load at each point + EI : -1 + diff --git a/gpkit/constraints/set.py b/gpkit/constraints/set.py index 3aca6b51a..8ea581103 100644 --- a/gpkit/constraints/set.py +++ b/gpkit/constraints/set.py @@ -48,6 +48,10 @@ def __getitem__(self, key): variables.sort(key=_var_sort_key) return variables + def __setitem__(self, key, value): + list.__setitem__(self, key, value) + self.reset_varkeys() + __str__ = _str __repr__ = _repr _repr_latex_ = _repr_latex_ From 750edcb3f316a6497ea015330a6e00b3553abb9d Mon Sep 17 00:00:00 2001 From: Edward Burnell Date: Fri, 5 Aug 2016 10:48:25 -0700 Subject: [PATCH 08/12] union -> update, lint in response to code review --- gpkit/constraints/costed.py | 2 +- gpkit/constraints/set.py | 4 ++-- gpkit/keydict.py | 12 ++++++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/gpkit/constraints/costed.py b/gpkit/constraints/costed.py index 517dc062b..b12524ed7 100644 --- a/gpkit/constraints/costed.py +++ b/gpkit/constraints/costed.py @@ -36,7 +36,7 @@ def reset_varkeys(self, init_dict=None): "Resets varkeys to what is in the cost and constraints" ConstraintSet.reset_varkeys(self, self.cost.varlocs) if init_dict is not None: - self.varkeys.union(init_dict) + self.varkeys.update(init_dict) def rootconstr_str(self, excluded=None): "The appearance of a ConstraintSet in addition to its contents" diff --git a/gpkit/constraints/set.py b/gpkit/constraints/set.py index 8ea581103..d54305c02 100644 --- a/gpkit/constraints/set.py +++ b/gpkit/constraints/set.py @@ -135,13 +135,13 @@ def subinplace(self, subs): def reset_varkeys(self, init_dict=None): "Goes through constraints and collects their varkeys." varkeys = KeySet() - if not init_dict is None: + if init_dict is not None: varkeys.update(init_dict) for constraint in self: if hasattr(constraint, "varkeys"): varkeys.update(constraint.varkeys) if hasattr(self, "unused_variables"): - varkeys.union(self.unused_variables) + varkeys.update(self.unused_variables) self.varkeys = varkeys def as_posyslt1(self): diff --git a/gpkit/keydict.py b/gpkit/keydict.py index f45bbb695..d39af3c1c 100644 --- a/gpkit/keydict.py +++ b/gpkit/keydict.py @@ -153,10 +153,14 @@ def add(self, item): "Adds an item to the keyset" self[item] = None - def union(self, iterable): - "Adds an iterable to the keyset" - for item in iterable: - self.add(item) + def update(self, *args, **kwargs): + "Iterates through the dictionary created by args and kwargs" + if len(args) == 1: + for item in args[0]: + self.add(item) + else: + for k, v in dict(*args, **kwargs).items(): + self[k] = v def __getitem__(self, key): "Gets the keys corresponding to a particular key." From 455e0b5368d6a2e7e9364f1e49373d7c09a0cab2 Mon Sep 17 00:00:00 2001 From: Edward Burnell Date: Fri, 5 Aug 2016 11:06:31 -0700 Subject: [PATCH 09/12] move unused_variables sub to a better location --- gpkit/constraints/costed.py | 8 -------- gpkit/constraints/set.py | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gpkit/constraints/costed.py b/gpkit/constraints/costed.py index b12524ed7..70901a97f 100644 --- a/gpkit/constraints/costed.py +++ b/gpkit/constraints/costed.py @@ -22,14 +22,6 @@ def __init__(self, cost, constraints, substitutions=None): def subinplace(self, subs): "Substitutes in place." self.cost = self.cost.sub(subs) - if hasattr(self, "unused_variables"): - unused_vars = [] - for var in self.unused_variables: - if var.key in subs: - unused_vars.append(subs[var.key]) - else: - unused_vars.append(var.key) - self.unused_variables = unused_vars ConstraintSet.subinplace(self, subs) def reset_varkeys(self, init_dict=None): diff --git a/gpkit/constraints/set.py b/gpkit/constraints/set.py index d54305c02..2f6141e17 100644 --- a/gpkit/constraints/set.py +++ b/gpkit/constraints/set.py @@ -131,6 +131,14 @@ def subinplace(self, subs): "Substitutes in place." for constraint in self: constraint.subinplace(subs) + if hasattr(self, "unused_variables"): + unused_vars = [] + for var in self.unused_variables: + if var.key in subs: + unused_vars.append(subs[var.key]) + else: + unused_vars.append(var.key) + self.unused_variables = unused_vars def reset_varkeys(self, init_dict=None): "Goes through constraints and collects their varkeys." From 7ea4b0f5910fdd877860ff0876617311d93ceacb Mon Sep 17 00:00:00 2001 From: Edward Burnell Date: Sat, 6 Aug 2016 02:15:10 -0700 Subject: [PATCH 10/12] recursively reset on subinplace --- gpkit/constraints/model.py | 1 - gpkit/constraints/set.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gpkit/constraints/model.py b/gpkit/constraints/model.py index 2104ab90c..b8f7ff726 100644 --- a/gpkit/constraints/model.py +++ b/gpkit/constraints/model.py @@ -98,7 +98,6 @@ def _add_modelname_tovars(self, name, num): del self.substitutions[vk] with SignomialsEnabled(): # since we're just substituting varkeys. self.subinplace(add_model_subs) - self.reset_varkeys() def subconstr_str(self, excluded=None): "The collapsed appearance of a ConstraintBase" diff --git a/gpkit/constraints/set.py b/gpkit/constraints/set.py index 2f6141e17..4ec19d973 100644 --- a/gpkit/constraints/set.py +++ b/gpkit/constraints/set.py @@ -139,6 +139,7 @@ def subinplace(self, subs): else: unused_vars.append(var.key) self.unused_variables = unused_vars + self.reset_varkeys() def reset_varkeys(self, init_dict=None): "Goes through constraints and collects their varkeys." From 30ff1bada95b8fe19e9b4274be8350f13332cfb6 Mon Sep 17 00:00:00 2001 From: Warren Hoburg Date: Fri, 5 Aug 2016 16:36:29 -0400 Subject: [PATCH 11/12] add test for lack of modelname appending --- gpkit/tests/t_model.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/gpkit/tests/t_model.py b/gpkit/tests/t_model.py index d44161c97..3c5b51fa3 100644 --- a/gpkit/tests/t_model.py +++ b/gpkit/tests/t_model.py @@ -418,7 +418,24 @@ def test_cvxopt_kwargs(self): self.assertAlmostEqual(sol["cost"], 12., NDIGS["cvxopt"]) -TESTS = [TestModelSolverSpecific] +class Thing(Model): + "a thing, for model testing" + def __init__(self, n, **kwargs): + a = VectorVariable(n, "a", "g/m") + b = VectorVariable(n, "b", "m") + c = Variable("c", 17/4., "g") + Model.__init__(self, None, [a >= c/b], **kwargs) + + +class TestModelNoSolve(unittest.TestCase): + """model tests that don't require a solver""" + def test_modelname_added(self): + t = Thing(2) + for vk in t.varkeys: + self.assertEqual(vk.models, ["Thing"]) + + +TESTS = [TestModelSolverSpecific, TestModelNoSolve] MULTI_SOLVER_TESTS = [TestGP, TestSP] for testcase in MULTI_SOLVER_TESTS: From 9a7122d38129f756e1614d540e8b20428dca01a1 Mon Sep 17 00:00:00 2001 From: Warren Hoburg Date: Sat, 6 Aug 2016 08:41:38 -0400 Subject: [PATCH 12/12] pylint attr accessed before def / defined outside init --- gpkit/constraints/set.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gpkit/constraints/set.py b/gpkit/constraints/set.py index 4ec19d973..33de27811 100644 --- a/gpkit/constraints/set.py +++ b/gpkit/constraints/set.py @@ -18,6 +18,7 @@ def __init__(self, constraints, substitutions=None, recursesubs=True): constraints = [constraints] list.__init__(self, constraints) subs = substitutions if substitutions else {} + self.unused_variables = None if not isinstance(constraints, ConstraintSet): # constraintsetify everything for i, constraint in enumerate(self): @@ -131,7 +132,7 @@ def subinplace(self, subs): "Substitutes in place." for constraint in self: constraint.subinplace(subs) - if hasattr(self, "unused_variables"): + if self.unused_variables is not None: unused_vars = [] for var in self.unused_variables: if var.key in subs: @@ -149,7 +150,7 @@ def reset_varkeys(self, init_dict=None): for constraint in self: if hasattr(constraint, "varkeys"): varkeys.update(constraint.varkeys) - if hasattr(self, "unused_variables"): + if self.unused_variables is not None: varkeys.update(self.unused_variables) self.varkeys = varkeys