import json
import re
import sys
import tempfile
from pathlib import Path
import numpy as np
import pounce
HERE = Path(__file__).resolve().parent
FIXTURES = HERE.parent / "fixtures_mpcc"
OUT = HERE / "cinterface_mpcc_python.json"
ROWS = [
("qpec_small", "qpec_small", []),
("ralph1", "ralph1", []),
("mixed_pair", "mixed_pair", []),
("design_cent_3", "design_cent_3", []),
("infeasible_pair", "infeasible_pair", []),
("opf_vv_lower_knee", "opf_vv_lower_knee", []),
("opf_vv_lower_knee_held", "opf_vv_lower_knee_held", []),
("qpec_small_exact", "qpec_small", ["complementarity_strategy=exact"]),
("qpec_small_continuation", "qpec_small", ["complementarity_strategy=continuation"]),
("qpec_small_schedule", "qpec_small", ["complementarity_continuation=schedule"]),
("qpec_small_lift_yes", "qpec_small", ["complementarity_lift=yes"]),
("qpec_small_lift_no", "qpec_small", ["complementarity_lift=no"]),
("qpec_small_lbfgs", "qpec_small", ["hessian_approximation=limited-memory"]),
("infeasible_pair_lbfgs_unmasked", "infeasible_pair", ["hessian_approximation=limited-memory"]),
("opf_vv_lower_knee_lbfgs_unmasked", "opf_vv_lower_knee", ["hessian_approximation=limited-memory"]),
(
"opf_vv_lower_knee_held_lbfgs_unmasked",
"opf_vv_lower_knee_held",
["hessian_approximation=limited-memory"],
),
]
RAW = "@@raw@@"
class NlCallbacks:
def __init__(self, nl):
self.nl = nl
def objective(self, x):
return self.nl.objective(x)
def gradient(self, x):
return self.nl.gradient(x)
def constraints(self, x):
return self.nl.constraints(x)
def jacobianstructure(self):
return self.nl.jacobian_structure()
def jacobian(self, x):
return self.nl.jacobian(x)
def hessianstructure(self):
return self.nl.hessian_structure()
def hessian(self, x, lagrange, obj_factor):
return self.nl.hessian(x, lagrange, obj_factor)
def option_value(v):
for kind in (int, float):
try:
return kind(v)
except ValueError:
pass
return v
def solve(fixture, options, report_path):
nl = pounce.read_nl(str(FIXTURES / f"{fixture}.nl"))
prob = pounce.Problem(
n=nl.n,
m=nl.m,
problem_obj=NlCallbacks(nl),
lb=list(nl.x_l),
ub=list(nl.x_u),
cl=list(nl.g_l),
cu=list(nl.g_u),
complementarity=[(r, v) for (r, v, _flags) in nl.complementarity],
)
prob.add_option("print_level", 0)
for o in options:
k, v = o.split("=", 1)
prob.add_option(k, option_value(v))
prob.solve(np.asarray(nl.x0, dtype=float), report_path=str(report_path), report_detail="full")
return json.loads(Path(report_path).read_text(), parse_float=lambda s: RAW + s)
def main():
rows = {}
with tempfile.TemporaryDirectory() as d:
for name, fixture, options in ROWS:
r = solve(fixture, options, Path(d) / f"{name}.json")
block = dict(r["complementarity"])
for s in block["solves"]:
s.pop("seconds", None)
rows[name] = {
"fixture": fixture,
"options": options,
"status": r["solution"]["status"],
"objective": r["solution"]["objective"],
"x": r["solution"]["x"],
"iteration_count": r["statistics"]["iteration_count"],
"complementarity": block,
}
print(name, block["total_iterations"], file=sys.stderr)
text = json.dumps({"generated_by": "pounce " + pounce.__version__, "rows": rows}, indent=1)
text = re.sub('"' + re.escape(RAW) + '([^"]*)"', r"\1", text)
OUT.write_text(text + "\n")
if __name__ == "__main__":
main()