From b27f702b161fdd536b921608f18319149a24487d Mon Sep 17 00:00:00 2001 From: Christoph Hansknecht Date: Mon, 27 May 2024 13:37:12 +0200 Subject: [PATCH 1/3] Add solver for MPS-encoded LPs --- pygradflow/runners/mps_runner.py | 91 ++++++++++++++++++++++++++++++++ pyproject.toml | 1 + 2 files changed, 92 insertions(+) create mode 100644 pygradflow/runners/mps_runner.py diff --git a/pygradflow/runners/mps_runner.py b/pygradflow/runners/mps_runner.py new file mode 100644 index 0000000..bb34283 --- /dev/null +++ b/pygradflow/runners/mps_runner.py @@ -0,0 +1,91 @@ +import os + +import mpspy +import numpy as np + +from pygradflow.problem import Problem +from pygradflow.util import sparse_zero + +from .instance import Instance +from .runner import Runner + + +class LinearProblem(Problem): + def __init__(self, instance): + self.instance = instance + + super().__init__( + var_lb=instance.var_lb, + var_ub=instance.var_ub, + cons_lb=instance.cons_lb, + cons_ub=instance.cons_ub, + ) + + def obj(self, x): + instance = self.instance + return np.dot(instance.obj, x) + + def obj_grad(self, x): + instance = self.instance + return instance.obj + + def cons(self, x): + instance = self.instance + coeffs = instance.coeffs + return coeffs.dot(x) + + def cons_jac(self, x): + instance = self.instance + return instance.coeffs + + def lag_hess(self, x, y): + num_vars = self.num_vars + return sparse_zero(shape=(num_vars, num_vars)) + + +class MPSInstance(Instance): + def __init__(self, instance): + self.instance = instance + + num_vars = instance.num_vars + num_cons = instance.num_cons + name = instance.name + + super().__init__(name, num_vars, num_cons) + + def problem(self): + return LinearProblem(self.instance) + + def x0(self): + instance = self.instance + num_vars = instance.num_vars + + x0 = np.zeros((num_vars,)) + + return np.clip(x0, instance.var_lb, instance.var_ub) + + +class MPSRunner(Runner): + def __init__(self): + super().__init__(name="mps") + + def get_instances(self, args): + instances = [] + for file in os.listdir(args.directory): + is_qplib = file.endswith(".mps") or file.endswith(".mps.gz") + + if is_qplib: + filename = os.path.join(args.directory, file) + description = mpspy.read_mps(filename) + instances.append(MPSInstance(description)) + + return instances + + def parser(self): + parser = super().parser() + parser.add_argument("directory") + return parser + + +if __name__ == "__main__": + MPSRunner().main() diff --git a/pyproject.toml b/pyproject.toml index 744a329..565001b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,7 @@ mypy = "^1.7.1" types-pyyaml = "^6.0.12" pytest-timeout = "^2.3.1" pyflakes = "^3.2.0" +mpspy = "^0.1.3" [tool.poetry.group.docs.dependencies] sphinx = "^7.2.6" From e625c1d6743bfd37aa15a5107f932be8dd62d5a2 Mon Sep 17 00:00:00 2001 From: Christoph Hansknecht Date: Mon, 27 May 2024 13:37:49 +0200 Subject: [PATCH 2/3] Fix bug in QPLIB runner --- pygradflow/runners/qplib_runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygradflow/runners/qplib_runner.py b/pygradflow/runners/qplib_runner.py index fd30453..eacfa97 100644 --- a/pygradflow/runners/qplib_runner.py +++ b/pygradflow/runners/qplib_runner.py @@ -35,10 +35,10 @@ def lag_hess(self, x, y): return self.problem.lag_hess(x, y) def x0(self): - return self.problem.x0() + return self.problem.x0 def y0(self): - return self.problem.y0() + return self.problem.y0 class QPLIBInstance(Instance): From 31e798c704a61e05078ce5fb1dc4b75d31379a87 Mon Sep 17 00:00:00 2001 From: Christoph Hansknecht Date: Mon, 27 May 2024 13:38:07 +0200 Subject: [PATCH 3/3] Bump version --- docs/conf.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index ca3c02e..4bdc759 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,7 +14,7 @@ project = "pygradflow" copyright = "2023, Christoph Hansknecht" author = "Christoph Hansknecht" -release = "0.5.1" +release = "0.5.2" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/pyproject.toml b/pyproject.toml index 565001b..6e0cc9b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pygradflow" -version = "0.5.1" +version = "0.5.2" description = "PyGradFlow is a simple implementation of the sequential homotopy method to be used to solve general nonlinear programs." authors = ["Christoph Hansknecht "] readme = "README.md"