From 9646be4f2d9ba3c59d3025b0a317dc8084973ed5 Mon Sep 17 00:00:00 2001 From: Gleb Belov Date: Tue, 19 Mar 2024 21:36:17 +1100 Subject: [PATCH] ModelExplorer: defined vars #232 --- CHANGES.mp.md | 21 ++++++++++++++++--- CMakeLists.txt | 2 +- src/expr-writer.h | 6 +----- support/modelexplore/scripts/python/model.py | 5 +++++ .../scripts/python/modelreader.py | 2 ++ 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/CHANGES.mp.md b/CHANGES.mp.md index 938108827..f4658c677 100644 --- a/CHANGES.mp.md +++ b/CHANGES.mp.md @@ -2,17 +2,32 @@ Summary of recent updates to the AMPL MP Library ================================================ -## unreleased +## 20240319 +- *SOS constraints*. + - Fixed handling of SOS2 constraints created by AMPL + as reformulations of PL expressions (`option + pl_linearize 1`, default; set to 0 to use the solver's + native PL functions if supported, or MP linearization.) + - Disallow repeated weights for SOS constraints + (suffixes `.sosno`/`.ref`.) +- *Reformulation explorer*. + - Upgraded option `writegraph` exports the reformulation + graph which can be explored with the script in + support/modelexplore (WIP.) - *Native handling of POW(x, INT)*. - Power expressions with positive integer exponent are passed natively to the solvers accepting them, vs previously quadratic or linear reformulation. - For best performance, global solving capability might be needed (e.g., Gurobi: `global=1`.) -- *Unused acc: options*. - - The constraint acceptance options *acc:...* +- *Option `report_times`*. +- *Unused `acc:` options*. + - The constraint acceptance options `acc:...` for non-handled constraints are ignored (previously triggered error.) +- *NLWPY*. + - Python NL Writer API for MIQP models. + - Available on PyPI. ## 20240115 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fd32445f..3dc9c06a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,7 +233,7 @@ endif() ## NOT SKIP_BUILD_MP include_directories(include) set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) -set(MP_DATE 20240115) +set(MP_DATE 20240319) set(MP_SYSINFO "${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR}") diff --git a/src/expr-writer.h b/src/expr-writer.h index 7587d5b7d..9fceb95e9 100644 --- a/src/expr-writer.h +++ b/src/expr-writer.h @@ -330,11 +330,7 @@ void ExprWriter::VisitPLTerm(PLTerm e) { for (int i = 1, n = e.num_slopes(); i < n; ++i) writer_ << ", " << e.slope(i); writer_ << ">> "; - NumericExpr arg = e.arg(); - if (Variable var = ExprTypes::template Cast(arg)) - writer_ << "x" << (var.index() + 1); - else - writer_ << "e" << ((ExprTypes::template Cast(arg)).index() + 1); + Visit( e.arg() ); } template diff --git a/support/modelexplore/scripts/python/model.py b/support/modelexplore/scripts/python/model.py index 38d256f03..2350b9bda 100644 --- a/support/modelexplore/scripts/python/model.py +++ b/support/modelexplore/scripts/python/model.py @@ -17,6 +17,7 @@ def __init__(self): self._graph = DiGraph() ## Underlyng graph self._vars = [] ## Pointers to various parts of the graph + self._dvars = [] self._cons_NL_all = [] self._cons_NL = { ## NL + SOS "All" : [], @@ -31,6 +32,9 @@ def __init__(self): def UpdateVar(self, idx, data): self._updateNodeData(self._vars, idx, data) + def UpdateDefVar(self, idx, data): + self._updateNodeData(self._dvars, idx, data) + def UpdateNLObj(self, idx, data): self._updateNodeData(self._objs_NL, idx, data) @@ -75,6 +79,7 @@ def _updateMap(self, data1, data2): def MatchOrigModel(self, keyw): result = {} result["NL Variables"] = self._matchRecords(self._vars, keyw, "is_from_nl") + result["NL Defined Variables"] = self._matchRecords(self._dvars, keyw) result["NL Objectives"] = self._matchRecords(self._objs_NL, keyw) result["NL Constraints"] \ = self._matchRecords(self._cons_NL.get("All"), keyw) diff --git a/support/modelexplore/scripts/python/modelreader.py b/support/modelexplore/scripts/python/modelreader.py index 4c7833d11..6cb86da44 100644 --- a/support/modelexplore/scripts/python/modelreader.py +++ b/support/modelexplore/scripts/python/modelreader.py @@ -31,6 +31,8 @@ def _processLine(self, line: str): def _addDataChunk(self, chunk): if "VAR_index" in chunk: self._model.UpdateVar(chunk["VAR_index"], chunk) + elif "NL_COMMON_EXPR_index" in chunk: + self._model.UpdateDefVar(chunk["NL_COMMON_EXPR_index"], chunk) elif "NL_OBJECTIVE_index" in chunk: self._model.UpdateNLObj(chunk["NL_OBJECTIVE_index"], chunk) elif "NL_CON_TYPE" in chunk: