Skip to content

Commit

Permalink
Export NL model: item names #232
Browse files Browse the repository at this point in the history
Generate names when needed and use for the flat model
  • Loading branch information
glebbelov committed Mar 13, 2024
1 parent e2c48b0 commit b8514e6
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 93 deletions.
43 changes: 24 additions & 19 deletions include/mp/flat/problem_flattener.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,19 @@ LinTerms ToLinTerms(const LinearExpr& e) {
}

/// Write algebraic expression (linear + non-linear.)
template <typename ExprTypes, typename LinearExpr, typename NumericExpr>
template <typename ExprTypes,
typename LinearExpr, typename NumericExpr,
typename Namer>
void WriteExpr(fmt::Writer &w, const LinearExpr &linear,
NumericExpr nonlinear);
NumericExpr nonlinear, Namer);

/// Write logical expression
template <typename ExprTypes, typename LogicalExpr>
void WriteExpr(fmt::Writer &w, LogicalExpr expr);
template <typename ExprTypes, typename LogicalExpr, class VN>
void WriteExpr(fmt::Writer &w, LogicalExpr expr, VN);

/// Write algebraic constraint.
template <class ExprTypes, class AlgCon>
void WriteAlgCon(fmt::Writer &w, const AlgCon &con);
template <class ExprTypes, class AlgCon, class VN>
void WriteAlgCon(fmt::Writer &w, const AlgCon &con, VN);


/// ProblemFlattener: it walks and "flattens" most expressions
Expand Down Expand Up @@ -135,8 +137,6 @@ class ProblemFlattener :
protected:
/// Convert problem items
void ConvertStandardItems() {
CopyItemNames();

////////////////////////// Variables
ConvertVars();

Expand Down Expand Up @@ -176,6 +176,10 @@ class ProblemFlattener :
MP_DISPATCH( ConvertLogicalCon( i ) );
}

/// We could have produced variable names
/// when exporting NL model info
CopyItemNames();

/// Signal we are not flattening anything
ifFltCon_ = -1;
}
Expand All @@ -188,11 +192,12 @@ class ProblemFlattener :
MiniJSONWriter jw(wrt);
jw["NL_COMMON_EXPR_index"] = i;
// We don't receive defvar names from AMPL
jw["name"] = "ce" + std::to_string(i+1);
auto vn = GetModel().GetVarNamer();
jw["name"] = vn.dvname(i);
auto ce = GetModel().common_expr(i);
fmt::MemoryWriter w2;
WriteExpr<typename ProblemType::ExprTypes>(
w2, ce.linear_expr(), ce.nonlinear_expr());
w2, ce.linear_expr(), ce.nonlinear_expr(), vn);
jw["printed"] = w2.c_str();
}
wrt.write("\n"); // EOL
Expand All @@ -207,13 +212,13 @@ class ProblemFlattener :
{
MiniJSONWriter jw(wrt);
jw["NL_OBJECTIVE_index"] = i;
if (GetModel().obj_names().size()>i)
jw["name"] = GetModel().obj_names()[i];
jw["name"] = GetModel().obj_name(i);
auto obj = GetModel().obj(i);
jw["sense"] = (int)obj.type();
fmt::MemoryWriter w2;
WriteExpr<typename ProblemType::ExprTypes>(
w2, obj.linear_expr(), obj.nonlinear_expr());
w2, obj.linear_expr(), obj.nonlinear_expr(),
GetModel().GetVarNamer());
jw["printed"] = w2.c_str();
}
wrt.write("\n"); // EOL
Expand All @@ -230,10 +235,10 @@ class ProblemFlattener :
auto con = GetModel().algebraic_con(i);
jw["NL_CON_TYPE"] = (con.nonlinear_expr() ? "nonlin" : "lin");
jw["index"] = i;
if (GetModel().con_names().size()>i)
jw["name"] = GetModel().con_names()[i];
jw["name"] = GetModel().con_name(i);
fmt::MemoryWriter w2;
WriteAlgCon<typename ProblemType::ExprTypes>(w2, con);
WriteAlgCon<typename ProblemType::ExprTypes>(
w2, con, GetModel().GetVarNamer());
jw["printed"] = w2.c_str();
}
wrt.write("\n"); // EOL
Expand All @@ -251,10 +256,10 @@ class ProblemFlattener :
jw["NL_CON_TYPE"] = "logical";
int i_actual = GetModel().num_algebraic_cons() + i;
jw["index"] = i_actual;
if (GetModel().con_names().size()>i_actual)
jw["name"] = GetModel().con_names()[i_actual];
jw["name"] = GetModel().con_name(i_actual);
fmt::MemoryWriter w2;
WriteExpr<typename ProblemType::ExprTypes>(w2, con.expr());
WriteExpr<typename ProblemType::ExprTypes>(
w2, con.expr(), GetModel().GetVarNamer());
jw["printed"] = w2.c_str();
}
wrt.write("\n"); // EOL
Expand Down
14 changes: 9 additions & 5 deletions include/mp/model-mgr-with-pb.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,21 +123,25 @@ class ModelManagerWithProblemBuilder :
/// The .row file has cons + objs.
void ReadNames(const std::string& namebase) {
if (WantNames()) {
NameProvider npv("_svar");
NameProvider npc("_scon");
NameProvider npv("_svar", "_sdvar");
NameProvider npc("_scon", "_slogcon");
if (WantNames()<=2) {
npv.ReadNames(namebase + ".col",
GetModel().num_vars());
GetModel().num_vars()
+ GetModel().num_common_exprs());
npc.ReadNames(namebase + ".row",
GetModel().num_cons()
+ GetModel().num_objs());
}
if (WantNames()>=2
|| npv.number_read()+npc.number_read()) {
GetModel().SetVarNames(
npv.get_names(GetModel().num_vars()));
npv.get_names(
GetModel().num_vars() + GetModel().num_common_exprs(),
GetModel().num_vars()));
GetModel().SetConNames(
npc.get_names(GetModel().num_cons()) );
npc.get_names(GetModel().num_cons(),
GetModel().num_algebraic_cons()) );
SetObjNames(npc);
}
}
Expand Down
16 changes: 11 additions & 5 deletions include/mp/nl-reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -2505,8 +2505,10 @@ class NameProvider {
fmt::CStringRef gen_name,
std::size_t num_items);

/// Construct without reading (generic names can be provided)
NameProvider(fmt::CStringRef gen_name);
/// Construct without reading (generic names can be provided).
/// @param n2: second generic name,
/// used from the 2nd index of name().
NameProvider(fmt::CStringRef gen_name, fmt::CStringRef n2="");

/// Read names
void ReadNames(fmt::CStringRef filename,
Expand All @@ -2516,15 +2518,19 @@ class NameProvider {
size_t number_read() const;

/// Returns the name of the item at specified index.
fmt::StringRef name(std::size_t index);
/// @param i2: if >=0,
/// from this index, generic name 2 is used
fmt::StringRef name(std::size_t index, std::size_t i2=-1);

/// Return vector of names, length n.
/// If number_read() < n, generic names are filled.
std::vector<std::string> get_names(size_t n);
/// @param i2: if >=0,
/// from this index, generic name 2 is used
std::vector<std::string> get_names(size_t n, size_t i2=-1);

private:
std::vector<const char *> names_;
std::string gen_name_;
std::string gen_name_, gen_name_2_;
internal::NameReader reader_;
fmt::MemoryWriter writer_;
};
Expand Down
63 changes: 61 additions & 2 deletions include/mp/problem.h
Original file line number Diff line number Diff line change
Expand Up @@ -475,14 +475,73 @@ class BasicProblem : public ExprFactory, public SuffixManager {
/** Returns the number of variables. */
int num_vars() const { return static_cast<int>(vars_.size()); }

/// Normal variable name
const std::string& var_name(int i) {
assert(0<=i && i<num_vars());
if ((int)var_names().size()<=i)
var_names_.resize(num_vars());
if (var_names_[i].empty())
var_names_[i] = "_x[" + std::to_string(i+1) + "]";
return var_names_[i];
}
/// Defined variable name
const std::string& dvar_name(int i) {
assert(0<=i && i<num_common_exprs());
i += num_vars();
if ((int)var_names().size()<=i)
var_names_.resize(num_vars()+num_common_exprs());
if (var_names_[i].empty())
var_names_[i] = "_sdvar[" + std::to_string(i+1) + "]";
return var_names_[i];
}
/// Constraint name
const std::string& con_name(int i) {
assert(0<=i && i<num_cons());
if ((int)con_names().size()<=i)
con_names_.resize(num_cons());
if (con_names_[i].empty())
con_names_[i]
= (i<num_algebraic_cons() ? "_CON" : "_LCON")
+ std::to_string(i+1);
return con_names_[i];
}
/// Objective name
const std::string& obj_name(int i) {
assert(0<=i && i<num_objs());
if ((int)obj_names().size()<=i)
obj_names_.resize(num_objs());
if (obj_names_[i].empty())
obj_names_[i] = "_OBJ" + std::to_string(i+1);
return obj_names_[i];
}

/** Returns the variable names (if present). */
/** Returns the variable names (if present).
* After normal variables follow defined variables.
*/
const std::vector<std::string>& var_names() { return var_names_; }
/** Returns the constraint names (if present). */
const std::vector<std::string>& con_names() { return con_names_; }
/** Returns the objective names (if present). */
const std::vector<std::string>& obj_names() { return obj_names_; }

/// Variable namer
class VarNamer {
public:
/// Construct
VarNamer(BasicProblem& p) : p_(p) { }
/// Normal var name
const std::string& vname(int i) const
{ return p_.var_name(i); }
/// Defined var name
const std::string& dvname(int i) const
{ return p_.dvar_name(i); }
private:
BasicProblem& p_;
};

/// Obtain variable namer
VarNamer GetVarNamer() { return VarNamer(*this); }

/** Returns the number of objectives. */
int num_objs() const { return static_cast<int>(linear_objs_.size()); }

Expand Down Expand Up @@ -669,7 +728,7 @@ class BasicProblem : public ExprFactory, public SuffixManager {

/// Set name vectors
void SetVarNames(std::vector<std::string> names) {
assert((size_t)num_vars() == names.size());
assert((size_t)(num_vars() + num_common_exprs()) == names.size());
var_names_ = std::move( names );
}
void SetConNames(std::vector<std::string> names) {
Expand Down
Loading

0 comments on commit b8514e6

Please sign in to comment.