Skip to content

Commit

Permalink
Names presolve v0.1 #209
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Jul 21, 2023
1 parent db10b80 commit b63cea3
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 34 deletions.
12 changes: 11 additions & 1 deletion include/mp/flat/constr_general.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,18 @@ class SOS_1or2_Constraint: public BasicConstraint {

/// Constructor
template <class VV=std::vector<int>, class WV=std::vector<double> >
SOS_1or2_Constraint(VV v, WV w, SOSExtraInfo ei={}) :
SOS_1or2_Constraint(VV v, WV w,
SOSExtraInfo ei, std::string nm={}) :
v_(v), w_(w), extra_info_(ei) {
SetName(std::move(nm));
sort();
assert(check());
}
/// Constructor
template <class VV=std::vector<int>, class WV=std::vector<double> >
SOS_1or2_Constraint(VV v, WV w, std::string nm={}) :
v_(v), w_(w) {
SetName(std::move(nm));
sort();
assert(check());
}
Expand Down
17 changes: 17 additions & 0 deletions include/mp/flat/constr_keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ class BasicConstraintKeeper {
/// Mark as deleted, use index only
virtual void MarkAsDeleted(int i) = 0;

/// Copy names from ValueNodes
virtual void CopyNamesFromValueNodes() = 0;


protected:
int& GetAccLevRef() { return acceptance_level_; }
Expand Down Expand Up @@ -480,6 +483,14 @@ class ConstraintKeeper : public BasicConstraintKeeper {
MarkAsDeleted(cons_.at(i), i);
}

/// Copy names from ValueNodes
void CopyNamesFromValueNodes() override {
const auto& vn = GetValueNode().GetStrVec();
assert(vn.size()==cons_.size());
for (auto i=vn.size(); i--; )
cons_[i].con_.SetName(vn[i].MakeCurrentName());
}

/// ForEachActive().
/// Deletes every constraint where fn() returned true.
template <class Fn>
Expand Down Expand Up @@ -702,6 +713,12 @@ class ConstraintManager {
}
}

/// Copy names from ValueNodes
void CopyNamesFromValueNodes() {
for (const auto& ck: con_keepers_)
ck.second.CopyNamesFromValueNodes();
}

/// Add all unbridged constraints to Backend
void AddUnbridgedConstraintsToBackend(
BasicFlatModelAPI& be) const {
Expand Down
42 changes: 38 additions & 4 deletions include/mp/flat/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ class FlatConverter :
GetModel().RelaxIntegrality();
FixUnusedDefinedVars(); // Until we have proper var deletion
CheckLinearCons();
PresolveNames();
GetModel().PushModelTo(GetModelAPI());
MPD( CloseGraphExporter() );
if (value_presolver_.GetExport())
Expand Down Expand Up @@ -524,6 +525,29 @@ class FlatConverter :
} );
}

/// Presolve item names
void PresolveNames() {
if (var_names_.size()) {
/// Check that constr / obj names are present too?
GetValuePresolver().CleanUpNameNodes();
auto vm = GetValuePresolver().
PresolveNames({
{var_names_},
{con_names_},
{obj_names_}
});
const auto& vcs = vm.GetVarValues()(); // vars
std::vector<std::string> vs(vcs.begin(), vcs.end());
BaseFlatModel::AddVarNames(vs);
const auto& ocs = vm.GetObjValues()(); // objs
auto& obj = BaseFlatModel::get_objectives();
assert(obj.size() == ocs.size());
for (auto i=obj.size(); i--;)
obj[i].set_name(ocs[i]);
ConstraintManager::CopyNamesFromValueNodes(); // cons
}
}

/// Fill model traits for license check.
/// To be called after ConvertModel().
/// KEEP THIS UP2DATE.
Expand Down Expand Up @@ -621,8 +645,14 @@ class FlatConverter :
return AutoLink( GetVarValueNode().Add( lbs.size() ) );
}

void AddVarNames(const std::vector<std::string>& names) {
BaseFlatModel::AddVars__names(names);
void AddVarNames(std::vector<std::string> names) {
var_names_ = std::move(names);
}
void AddConNames(std::vector<std::string> names) {
con_names_ = std::move(names);
}
void AddObjNames(std::vector<std::string> names) {
obj_names_ = std::move(names);
}
/// Reuse ValuePresolver's target nodes for all variables
pre::ValueNode& GetVarValueNode()
Expand Down Expand Up @@ -724,8 +754,6 @@ class FlatConverter :
pre::NodeRange DoAddVar(double lb=MinusInfty(), double ub=Infty(),
var::Type type = var::CONTINUOUS) {
int v = GetModel().AddVar__basic(lb, ub, type);
GetModel().AddVar__name();

return AutoLink( GetVarValueNode().Select( v ) );
}

Expand Down Expand Up @@ -1022,6 +1050,12 @@ class FlatConverter :

std::vector<int> refcnt_vars_;

/// AMPL item names
std::vector<std::string>
var_names_,
con_names_, // no SOS here, they go directly into the SOS
obj_names_;


protected:
/////////////////////// CONSTRAINT KEEPERS /////////////////////////
Expand Down
10 changes: 3 additions & 7 deletions include/mp/flat/converter_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,8 @@ class FlatModel
assert(check_vars());
}

void AddVar__name() {
if(var_names_storage_.size()>0)
var_names_storage_.push_back(fmt::format("mpv_{}", var_names_storage_.size()));
}
void AddVars__names(const std::vector<std::string>& names) {
var_names_storage_.insert(var_names_storage_.end(), names.begin(), names.end());
void AddVarNames(const std::vector<std::string>& names) {
var_names_storage_ = names;
}

int num_vars() const
Expand Down Expand Up @@ -203,9 +199,9 @@ class FlatModel
auto fmi = CreateFlatModelInfo();
FillConstraintCounters(backend, *fmi.get());
backend.PassFlatModelInfo(std::move(fmi));

backend.InitProblemModificationPhase(
backend.GetFlatModelInfo());

PushVariablesTo(backend);
PushObjectivesTo(backend);
PushCustomConstraintsTo(backend);
Expand Down
2 changes: 2 additions & 0 deletions include/mp/flat/obj_std.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class LinearObjective {
const std::vector<int>& vars() const { return vars_; }
/// Name
const char* name() const { return name_.c_str(); }
/// Set name
void set_name(std::string nm) { name_ = std::move(nm); }

/// Testing API
bool operator==(const LinearObjective& lc) const {
Expand Down
27 changes: 21 additions & 6 deletions include/mp/flat/problem_flattener.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ class ProblemFlattener :
protected:
/// Convert problem items
void ConvertStandardItems() {
CopyItemNames();

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

Expand Down Expand Up @@ -165,7 +167,6 @@ class ProblemFlattener :
}

auto vnr = GetFlatCvt().AddVars(lbs, ubs, types);
GetFlatCvt().AddVarNames(GetModel().var_names());
GetCopyLink().AddEntry({
GetValuePresolver().GetSourceNodes().GetVarValues().MakeSingleKey().
Add(lbs.size()),
Expand Down Expand Up @@ -310,6 +311,12 @@ class ProblemFlattener :
assert(GetFlatCvt().HasInitExpression(resvar));
}

void CopyItemNames() {
GetFlatCvt().AddVarNames(GetModel().var_names());
GetFlatCvt().AddConNames(GetModel().con_names());
GetFlatCvt().AddObjNames(GetModel().obj_names());
}


protected:
//////////////////////////////////// VISITOR ADAPTERS /////////////////////////////////////////
Expand Down Expand Up @@ -812,12 +819,20 @@ class ProblemFlattener :
vars.push_back(wv.second);
}
if (group.first<0 || fAllSOS2)
AddConstraint(SOS2Constraint(vars, weights,
fAllSOS2 ?
SOSExtraInfo{{1.0, 1.0}} : // for linearized PL
SOSExtraInfo{}));
AddConstraint(
SOS2Constraint(vars, weights,
fAllSOS2 ? // for linearized PL
SOSExtraInfo{{1.0, 1.0}} :
SOSExtraInfo{},
(fAllSOS2 ? "SOS2_PL_" : "SOS2_")
+ std::to_string(group.first)
+ '_'));
else
AddConstraint(SOS1Constraint(vars, weights));
AddConstraint(
SOS1Constraint(vars, weights,
"SOS1_"
+ std::to_string(group.first)
+ '_'));
}
}

Expand Down
2 changes: 1 addition & 1 deletion include/mp/flat/redef/MIP/piecewise_linear.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class PLConverter_MIP :
std::iota(weights.begin(), weights.end(), 1.0);
GetMC().AddConstraint( // indicate range of sum(lambda)
SOS2Constraint(lambda, weights,
{ {1.0, 1.0} }) );
SOSExtraInfo{ {1.0, 1.0} }) );
std::fill(weights.begin(), weights.end(), 1.0);
GetMC().AddConstraint(
LinConEQ{ {weights, lambda}, {1.0} });
Expand Down
2 changes: 1 addition & 1 deletion include/mp/flat/redef/std/range_con.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class RangeCon2Slack :
SetStr(be, CON_TARGET, GetStr(be, CON_SRC) + "_equ_");
}
/// Postsolve names: none
void PostsolveNamesEntry(const typename Base::LinkEntry& be) { }
void PostsolveNamesEntry(const typename Base::LinkEntry& ) { }


protected:
Expand Down
6 changes: 3 additions & 3 deletions include/mp/model-mgr-with-pb.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,9 @@ class ModelManagerWithProblemBuilder :
{ "1", "Only provide names if at least one of "
".col / .row name files was written by AMPL "
"(AMPL options auxfiles, <solver>_auxfiles)", 1},
{ "2", "Read names from AMPL, but provide generic "
"names otherwise", 2},
{ "3", "Provide generic names.", 3}
{ "2", "Read names from AMPL, but create generic "
"names if not provided", 2},
{ "3", "Create generic names.", 3}
};

struct Options {
Expand Down
6 changes: 5 additions & 1 deletion include/mp/problem.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,11 @@ class BasicProblem : public ExprFactory, public SuffixManager {

/** Returns the variable names (if present). */
std::vector<std::string>& var_names() { return var_names_; }

/** Returns the constraint names (if present). */
std::vector<std::string>& con_names() { return con_names_; }
/** Returns the objective names (if present). */
std::vector<std::string>& obj_names() { return obj_names_; }

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

Expand Down
66 changes: 61 additions & 5 deletions include/mp/valcvt-base.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ class ValueMap {

/// Construct from a single SomeArray
template <class SomeArray>
ValueMap(SomeArray r) :
map_{ {0, std::move(r) } } {
ValueMap(const SomeArray& r) {
Array a(r.begin(), r.end());
map_[0] = std::move(a);
SetValueNodeName(map_.at(0), name_ + "()");
}

Expand Down Expand Up @@ -271,15 +272,70 @@ using MVOverEl = ModelValues< VMapOverElement<El> >;
using ModelValuesInt = MVOverEl< int >;
/// Specialize ModelValues<> for concrete double data
using ModelValuesDbl = MVOverEl< double >;
/// Specialize ModelValues<> for concrete double data
/// Specialize ModelValues<> for concrete string data
using ModelValuesStr = MVOverEl< std::string >;


/// Declare ValueNode
class ValueNode;

/// Typedef VCString
using VCString = std::string;

/// Typedef VCString.
/// This class stores node names
/// and counts references to a given name
/// and allows numbering derived items
/// 'Con01_1_', ...
class VCString {
public:
/// Construct default
VCString() = default;
/// Construct from string
VCString(std::string s) : s_(std::move(s)) { }
/// Copy from VCString.
/// Updates its counter,
/// but inits own counter to 0.
VCString(const VCString& vcs)
: s_(vcs.MakeCountedName()) { }
/// Assign VCString.
/// Only if empty (then copy.)
VCString& operator=(const VCString& vcs) {
if (empty()) {
s_ = vcs.MakeCountedName();
assert(!n_);
}
return *this;
}

/// Return current name, unmodified.
const std::string& MakeCurrentName() const
{ return s_; }

/// Produce name s + '_<counter>_' if n_>0.
/// Post-increment counter.
std::string MakeCountedName() const {
return
n_++==0
? s_
: s_ + '_' + std::to_string(n_) + '_';
}
/// Use MakeCountedName().
operator std::string() const
{ return MakeCountedName(); }
/// Produce another VCString with
/// an added string or char.
/// Does not change own counter,
/// we assume the caller cares for name uniqueness.
template <class T>
VCString operator+(const T& arg) const
{ return {s_ + arg}; }

/// empty?
bool empty() const { return s_.empty(); }

private:
std::string s_;
mutable std::size_t n_ = 0;
};

/// Macro for a list of pre- / postsolve method definitions
/// in a ValuePresolver or a link.
Expand Down
12 changes: 10 additions & 2 deletions include/mp/valcvt-node.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ class ValueNode {
/// Retrieve whole vector<VCString&>&
operator const std::vector<VCString>& () const { return vStr_; }

/// Retrieve whole vector<VCString&>&
const std::vector<VCString>& GetStrVec() const { return vStr_; }


/////////////////////// Access individual values ///////////////////////

Expand Down Expand Up @@ -253,10 +256,15 @@ class ValueNode {
/// SetName
void SetName(std::string s) { name_ = std::move(s); }

/// Clean up and realloc with current size, fill by 0's
/// Clean up and realloc with current size, fill by 0's.
/// Numeric arrays only.
void CleanUpAndRealloc() {
vi_.clear(); vd_.clear(); vStr_.clear();
vi_.clear(); vd_.clear();
vi_.resize(Size()); vd_.resize(Size());
}
/// Clean up and realloc names.
void CleanUpAndRealloc_Names() {
vStr_.clear();
vStr_.resize(Size());
}

Expand Down
Loading

0 comments on commit b63cea3

Please sign in to comment.