diff --git a/include/mp/flat/converter_model.h b/include/mp/flat/converter_model.h index 2d1a12b78..63abf7793 100644 --- a/include/mp/flat/converter_model.h +++ b/include/mp/flat/converter_model.h @@ -262,8 +262,12 @@ class FlatModel { MiniJSONWriter jw(wrt); jw["OBJECTIVE_index"] = i_obj; - if (*obj.name()) + if (obj.name() && *obj.name()) { jw["name"] = obj.name(); + fmt::MemoryWriter pr; + WriteModelItem(pr, obj, var_names_storage_); + jw["printed"] = pr.c_str(); + } jw["sense"] = (int)obj.obj_sense(); WriteJSON(jw["qp_terms"], obj.GetQPTerms()); WriteJSON(jw["lin_terms"], obj.GetLinTerms()); diff --git a/include/mp/flat/expr_algebraic.h b/include/mp/flat/expr_algebraic.h index 5f147ac13..5c12c1842 100644 --- a/include/mp/flat/expr_algebraic.h +++ b/include/mp/flat/expr_algebraic.h @@ -112,6 +112,11 @@ class AlgebraicExpression : public Body { double constant_term_ = 0.0; }; +/// Very general template to write any flat con/obj +template +void WriteModelItem(Writer& wrt, const Item& i, + const std::vector& vnam); + /// Very general template to write /// a JSON-like representation of anything template diff --git a/include/mp/flat/problem_flattener.h b/include/mp/flat/problem_flattener.h index c2f309730..647c92dfe 100644 --- a/include/mp/flat/problem_flattener.h +++ b/include/mp/flat/problem_flattener.h @@ -196,6 +196,7 @@ class ProblemFlattener : jw["name"] = vn.dvname(i); auto ce = GetModel().common_expr(i); fmt::MemoryWriter w2; + w2 << "var " << vn.dvname(i) << " = "; WriteExpr( w2, ce.linear_expr(), ce.nonlinear_expr(), vn); jw["printed"] = w2.c_str(); @@ -216,6 +217,8 @@ class ProblemFlattener : auto obj = GetModel().obj(i); jw["sense"] = (int)obj.type(); fmt::MemoryWriter w2; + w2 << (obj::MAX==obj.type() ? "maximize " : "minimize "); + w2 << GetModel().obj_name(i) << ": "; WriteExpr( w2, obj.linear_expr(), obj.nonlinear_expr(), GetModel().GetVarNamer()); @@ -237,6 +240,7 @@ class ProblemFlattener : jw["index"] = i; jw["name"] = GetModel().con_name(i); fmt::MemoryWriter w2; + w2 << GetModel().con_name(i) << ": "; WriteAlgCon( w2, con, GetModel().GetVarNamer()); jw["printed"] = w2.c_str(); @@ -258,6 +262,7 @@ class ProblemFlattener : jw["index"] = i_actual; jw["name"] = GetModel().con_name(i_actual); fmt::MemoryWriter w2; + w2 << GetModel().con_name(i_actual) << ": "; WriteExpr( w2, con.expr(), GetModel().GetVarNamer()); jw["printed"] = w2.c_str(); diff --git a/src/std_constr.cc b/src/std_constr.cc index ed8f8364a..133f64cff 100644 --- a/src/std_constr.cc +++ b/src/std_constr.cc @@ -7,6 +7,7 @@ #include "mp/common.h" #include "mp/flat/expr_quadratic.h" +#include "mp/flat/obj_std.h" #include "mp/flat/model_info.hpp" namespace mp { @@ -89,7 +90,52 @@ void WriteVar(Writer& pr, const char* name, if (var::INTEGER == ty) pr << " integer"; } - pr << ';'; +} + + template <> + void WriteModelItem(fmt::MemoryWriter& wrt, const LinTerms& lt, + const std::vector& vnam) { + for (int i=0; i<(int)lt.size(); ++i) { + if (i) { + wrt << (lt.coef(i)>=0.0 ? " + " : " - "); + } + wrt << std::fabs(lt.coef(i)) << '*' << vnam.at(lt.var(i)); + } +} + +template <> +void WriteModelItem(fmt::MemoryWriter& wrt, const QuadTerms& qt, + const std::vector& vnam) { + for (int i=0; i<(int)qt.size(); ++i) { + if (i) { + wrt << (qt.coef(i)>=0.0 ? " + " : " - "); + } + wrt << std::fabs(qt.coef(i)) + << '*' << vnam.at(qt.var1(i)) + << '*' << vnam.at(qt.var2(i)); + } +} + +template <> +void WriteModelItem(fmt::MemoryWriter& wrt, const QuadAndLinTerms& qlt, + const std::vector& vnam) { + +} + +template <> +void WriteModelItem(fmt::MemoryWriter& wrt, const QuadraticObjective& obj, + const std::vector& vnam) { + wrt << (obj.obj_sense() ? "maximize " : "minimize "); + assert(obj.name() && *obj.name()); + wrt << obj.name() << ": "; + WriteModelItem(wrt, obj.GetLinTerms(), vnam); + if (obj.GetQPTerms().size()) { + if (obj.GetLinTerms().size()) + wrt << " + "; + wrt << '('; + WriteModelItem(wrt, obj.GetQPTerms(), vnam); + wrt << ')'; + } } // Generate diff --git a/support/modelexplore/scripts/python/model.py b/support/modelexplore/scripts/python/model.py index 6e1800090..38d256f03 100644 --- a/support/modelexplore/scripts/python/model.py +++ b/support/modelexplore/scripts/python/model.py @@ -108,6 +108,9 @@ def _matchRecords(self, cnt, keyw, keyNeed1=None): pr = str(i) ## TODO printed form if "printed" in i: pr = i["printed"] + assert len(pr) + if ';'!=pr[-1]: + pr = pr + ';' if (""==keyw or keyw in pr) \ and (keyNeed1==None \ or (keyNeed1 in i and 1==i[keyNeed1])):