Skip to content

Commit

Permalink
checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
bqpd committed Jul 15, 2021
1 parent ce48f49 commit 0df34d2
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 222 deletions.
341 changes: 163 additions & 178 deletions gpkit/breakdown.py

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions gpkit/constraints/gp.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,14 +358,15 @@ def _compile_result(self, solver_out):
# carry linked sensitivities over to their constants
for v in list(v for v in gpv_ss if v.gradients):
dlogcost_dlogv = gpv_ss.pop(v)
dlogcost_dlogvtw = absv_ss.pop(v)
dlogcost_dlogabsv = absv_ss.pop(v)
val = np.array(result["constants"][v])
for c, dv_dc in v.gradients.items():
with pywarnings.catch_warnings(): # skip pesky divide-by-zeros
pywarnings.simplefilter("ignore")
dlogv_dlogc = dv_dc * result["constants"][c]/val
gpv_ss[c] = gpv_ss.get(c, 0) + dlogcost_dlogv*dlogv_dlogc
absv_ss[c] = absv_ss.get(c, 0) + abs(dlogcost_dlogvtw*dlogv_dlogc)
absv_ss[c] = (absv_ss.get(c, 0)
+ abs(dlogcost_dlogabsv*dlogv_dlogc))
if v in cost_senss:
if c in self.cost.vks: # TODO: seems unnecessary
dlogcost_dlogv = cost_senss.pop(v)
Expand Down
10 changes: 4 additions & 6 deletions gpkit/constraints/prog_factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ def evaluate_linked(constants, linked):
kdc_plain = None
array_calulated = {}
for key in constants: # remove gradients from constants
if key.gradients:
del key.descr["gradients"]
key.descr.pop("gradients", None)
for v, f in linked.items():
try:
if v.veckey and v.veckey.vecfn:
Expand Down Expand Up @@ -48,10 +47,9 @@ def evaluate_linked(constants, linked):
constants[v] = out
continue # a new fixed variable, not a calculated one
constants[v] = out.x
gradients = {adn.tag:
grad for adn, grad in out.d().items() if adn.tag}
if gradients:
v.descr["gradients"] = gradients
v.descr["gradients"] = {adn.tag: grad
for adn, grad in out.d().items()
if adn.tag}
except Exception as exception: # pylint: disable=broad-except
from .. import settings
if settings.get("ad_errors_raise", None):
Expand Down
21 changes: 11 additions & 10 deletions gpkit/constraints/set.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,21 +209,22 @@ def set_necessarylineage(self, clear=False):
shortname = key.str_without(["lineage", "vec"])
if len(self.varkeys[shortname]) > 1:
name_collisions[shortname].add(key)
for vks in name_collisions.values():
for varkeys in name_collisions.values():
min_namespaced = defaultdict(set)
for vk in vks:
for vk in varkeys:
*_, mineage = vk.lineagestr().split(".")
min_namespaced[(mineage, 1)].add(vk)
while any(len(vks) > 1 for vks in min_namespaced.values()):
for key, vks in list(min_namespaced.items()):
if len(vks) > 1:
del min_namespaced[key]
mineage, idx = key
idx += 1
for vk in vks:
lineages = vk.lineagestr().split(".")
submineage = lineages[-idx] + "." + mineage
min_namespaced[(submineage, idx)].add(vk)
if len(vks) <= 1:
continue
del min_namespaced[key]
mineage, idx = key
idx += 1
for vk in vks:
lineages = vk.lineagestr().split(".")
submineage = lineages[-idx] + "." + mineage
min_namespaced[(submineage, idx)].add(vk)
for (_, idx), vks in min_namespaced.items():
vk, = vks
self._name_collision_varkeys[vk] = idx
Expand Down
21 changes: 11 additions & 10 deletions gpkit/constraints/sgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class SequentialGeometricProgram:
slack = Variable("C")

def __init__(self, cost, model, substitutions,
*, use_pccp=True, pccp_penalty=2e2, checkbounds=True, **_):
*, use_pccp=True, pccp_penalty=2e2, **kwargs):
self.pccp_penalty = pccp_penalty
if cost.any_nonpositive_cs:
raise InvalidPosynomial("""an SGP's cost must be Posynomial
Expand Down Expand Up @@ -92,7 +92,7 @@ def __init__(self, cost, model, substitutions,
solutions and can be solved with 'Model.solve()'.""")
self._gp = GeometricProgram(
cost, self.approxconstraints + self.gpconstraints,
substitutions, checkbounds=checkbounds)
substitutions, **kwargs)
self._gp.x0 = x0
self.a_idxs = defaultdict(list)
cost_mons = self._gp.k[0]
Expand Down Expand Up @@ -176,7 +176,8 @@ def localsolve(self, solver=None, *, verbosity=1, x0=None, reltol=1e-4,
" GP solve %i. Details can be found in `m.program.results`"
" or by solving at a higher verbosity. Note convergence"
" is not guaranteed for models with SignomialEqualities."
% (100*(cost - prevcost)/prevcost, prevcost, cost, len(self.gps)))
% (100*(cost - prevcost)/prevcost,
prevcost, cost, len(self.gps)))
rel_improvement = cost = None
# solved successfully!
self.result = gp.generate_result(solver_out, verbosity=verbosity-3)
Expand All @@ -196,13 +197,13 @@ def localsolve(self, solver=None, *, verbosity=1, x0=None, reltol=1e-4,
"Slack Non-GP Constraints")
if verbosity > -1:
print(msg +
" Calling .localsolve(pccp_penalty=...) with a"
" higher `pccp_penalty` (it was %.3g this time) will"
" reduce slack if the model is solvable with less. To"
" verify that the slack is needed, generate an SGP with"
" `use_pccp=False` and start it from this model's"
" solution: e.g. `m.localsolve(use_pccp=False, x0="
"m.solution[\"variables\"])`." % self.pccp_penalty)
" Calling .localsolve(pccp_penalty=...) with a"
" higher `pccp_penalty` (it was %.3g this time) will"
" reduce slack if the model is solvable with less. To"
" verify that the slack is needed, generate an SGP"
" with `use_pccp=False` and start it from this model"
"'s solution: e.g. `m.localsolve(use_pccp=False, x0="
"m.solution[\"variables\"])`." % self.pccp_penalty)
del self.result["freevariables"][self.slack.key] # pylint: disable=no-member
del self.result["variables"][self.slack.key] # pylint: disable=no-member
del self.result["sensitivities"]["variables"][self.slack.key] # pylint: disable=no-member
Expand Down
29 changes: 15 additions & 14 deletions gpkit/solution_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import pickle
import gzip
import pickletools
import numpy as np
from collections import defaultdict
import numpy as np
from .nomials import NomialArray
from .small_classes import DictOfLists, Strings
from .small_scripts import mag, try_str_without
Expand Down Expand Up @@ -182,7 +182,8 @@ def constraint_table(data, title, sortbymodel=True, showmodels=True, **_):
model = lineagestr(constraint) if sortbymodel else ""
if model not in models:
models[model] = len(models)
constrstr = try_str_without(constraint, excluded + (":MAGIC:"+lineagestr(constraint),))
constrstr = try_str_without(
constraint, excluded + (":MAGIC:"+lineagestr(constraint),))
if " at 0x" in constrstr: # don't print memory addresses
constrstr = constrstr[:constrstr.find(" at 0x")] + ">"
decorated.append((models[model], model, sortby, constrstr, openingstr))
Expand All @@ -196,7 +197,6 @@ def constraint_table(data, title, sortbymodel=True, showmodels=True, **_):
if model or lines:
lines.append([("newmodelline",), model])
previous_model = model
# constrstr = constrstr.replace(model, "")
minlen, maxlen = 25, 80
segments = [s for s in CONSTRSPLITPATTERN.split(constrstr) if s]
constraintlines = []
Expand Down Expand Up @@ -368,26 +368,27 @@ def set_necessarylineage(self, clear=False):
self["variables"].update_keymap()
keymap = self["variables"].keymap
name_collisions = defaultdict(set)
for key in list(keymap):
for key in keymap:
if hasattr(key, "key"):
shortname = key.str_without(["lineage", "vec"])
if len(keymap[shortname]) > 1:
name_collisions[shortname].add(key)
for vks in name_collisions.values():
for varkeys in name_collisions.values():
min_namespaced = defaultdict(set)
for vk in vks:
for vk in varkeys:
*_, mineage = vk.lineagestr().split(".")
min_namespaced[(mineage, 1)].add(vk)
while any(len(vks) > 1 for vks in min_namespaced.values()):
for key, vks in list(min_namespaced.items()):
if len(vks) > 1:
del min_namespaced[key]
mineage, idx = key
idx += 1
for vk in vks:
lineages = vk.lineagestr().split(".")
submineage = lineages[-idx] + "." + mineage
min_namespaced[(submineage, idx)].add(vk)
if len(vks) <= 1:
continue
del min_namespaced[key]
mineage, idx = key
idx += 1
for vk in vks:
lineages = vk.lineagestr().split(".")
submineage = lineages[-idx] + "." + mineage
min_namespaced[(submineage, idx)].add(vk)
for (_, idx), vks in min_namespaced.items():
vk, = vks
self._name_collision_varkeys[vk] = idx
Expand Down
2 changes: 0 additions & 2 deletions gpkit/varkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ def str_without(self, excluded=()):
name = self.name
if "lineage" not in excluded and self.lineage:
namespace = self.lineagestr("modelnums" not in excluded).split(".")
backscan = 0
for ex in excluded:
if ex[0:7] == ":MAGIC:":
to_replace = ex[7:].split(".")
Expand All @@ -77,7 +76,6 @@ def str_without(self, excluded=()):
namespace = namespace[1:]
if len(to_replace) > replaced:
namespace.insert(0, "."*(len(to_replace)-replaced))
backscan = replaced - 1
if "unnecessary lineage" in excluded:
if self.necessarylineage:
namespace = namespace[-self.necessarylineage:]
Expand Down

0 comments on commit 0df34d2

Please sign in to comment.