Skip to content

Commit

Permalink
Some SOCP redefinitions #192
Browse files Browse the repository at this point in the history
Not in Mosek yet
  • Loading branch information
glebbelov committed Feb 24, 2023
1 parent eef1a5f commit b2b5d41
Show file tree
Hide file tree
Showing 11 changed files with 356 additions and 58 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ add_prefix(MP_FLAT_REDEF_HEADERS include/mp/flat/redef/
add_prefix(MP_FLAT_REDEF_STD_HEADERS include/mp/flat/redef/std/
range_con.h)

add_prefix(MP_FLAT_REDEF_STD_HEADERS include/mp/flat/redef/conic/
cones.h)

add_prefix(MP_FLAT_REDEF_MIP_HEADERS include/mp/flat/redef/MIP/
converter_mip.h redefs_mip_std.h abs.h alldiff.h
cond_eq.h cond_ineq.h complement.h count.h
Expand Down
46 changes: 39 additions & 7 deletions include/mp/flat/constr_keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,9 @@ class BasicFlatConverter {
/// -Infinity
static constexpr double MinusInfty() { return -INFINITY; }
/// Pract inf
static constexpr double PracticallyInfty() { return 1e20; }
static constexpr double PracticallyInf() { return 1e20; }
/// Pract -inf
static constexpr double PracticallyMinusInfty() { return -1e20; }
static constexpr double PracticallyMinusInf() { return -1e20; }
};


Expand Down Expand Up @@ -405,6 +405,7 @@ class ConstraintKeeper : public BasicConstraintKeeper {

/// Check constraint index
bool check_index(int i) const { return i>=0 && i<(int)cons_.size(); }

/// Container for a single constraint
struct Container {
Container(Constraint&& c) noexcept : con_(std::move(c)) { }
Expand All @@ -415,6 +416,8 @@ class ConstraintKeeper : public BasicConstraintKeeper {
Constraint con_;
bool is_bridged_ = false;
};

/// Convert all new constraints of this type
bool ConvertAllFrom(int& i_last) {
int i=i_last;
const auto acceptanceLevel =
Expand Down Expand Up @@ -446,17 +449,44 @@ class ConstraintKeeper : public BasicConstraintKeeper {
i_last = i-1;
return any_converted;
}
/// Call Converter's RunConversion() and mark as "bridged"

/// Call Converter's RunConversion() and mark as "bridged".
///
/// @param cnt the constraint container
/// actually redundant as i is enough to find. But for speed
/// @param cnt the constraint container -
/// actually redundant, as \a i is enough to find it. But for speed.
/// @param i constraint index, needed for bridging
void ConvertConstraint(Container& cnt, int i) {
assert(!cnt.IsBridged());
GetConverter().RunConversion(cnt.con_, i);
cnt.MarkAsBridged();
++n_bridged_;
MarkAsDeleted(cnt, i);
}

/// Mark item as deleted
void MarkAsDeleted(Container& cnt, int ) {
cnt.MarkAsBridged();
++n_bridged_;
}


public:
/// Mark as deleted, use index only
void MarkAsDeleted(int i) {
MarkAsDeleted(cons_.at(i), i);
}

/// ForEachActive().
/// Deletes every constraint where fn() returned true.
template <class Fn>
void ForEachActive(Fn fn) {
for (int i=0; i<(int)cons_.size(); ++i)
if (!cons_[i].IsBridged())
if (fn(cons_[i].con_, i))
MarkAsDeleted(cons_[i], i);
}


protected:
/// Add all non-converted items to ModelAPI
void AddAllUnbridged(BasicFlatModelAPI& be) {
int con_index=0;
auto con_group = GetConstraintGroup(be);
Expand Down Expand Up @@ -514,10 +544,12 @@ class ConstraintKeeper : public BasicConstraintKeeper {
/// constraint
#define STORE_CONSTRAINT_TYPE__INTERNAL( \
Constraint, optionNames) \
private: \
ConstraintKeeper<Impl, ModelAPI, Constraint> \
CONSTRAINT_KEEPER_VAR(Constraint) \
{*static_cast<Impl*>(this), \
#Constraint, optionNames}; \
public: \
const ConstraintKeeper<Impl, ModelAPI, Constraint>& \
GetConstraintKeeper(Constraint* ) const { \
return CONSTRAINT_KEEPER_VAR(Constraint); \
Expand Down
8 changes: 4 additions & 4 deletions include/mp/flat/constr_prepro.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,10 @@ class ConstraintPreprocessors {
auto& m = MPD( GetModel() );
auto v1 = c.GetArguments()[0], v2 = c.GetArguments()[1];
const auto l1=m.lb(v1), u1=m.ub(v1), l2=m.lb(v2), u2=m.ub(v2);
if (l1 > MPD( PracticallyMinusInfty() ) &&
u1 < MPD( PracticallyInfty() ) &&
l2 > MPD( PracticallyMinusInfty() ) &&
u2 < MPD( PracticallyInfty() ) &&
if (l1 > MPD( PracticallyMinusInf() ) &&
u1 < MPD( PracticallyInf() ) &&
l2 > MPD( PracticallyMinusInf() ) &&
u2 < MPD( PracticallyInf() ) &&
l2 * u2 > 0.0) {
auto l0 = std::numeric_limits<double>::max();
auto u0 = std::numeric_limits<double>::min();
Expand Down
4 changes: 2 additions & 2 deletions include/mp/flat/constr_prop_down.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ class ConstraintPropagatorsDown {
template <class Body>
void PropagateResult(AlgebraicConstraint<Body, AlgConRange>& con) {
/// Distinguish bounds' finiteness for context
auto ctx = con.lb()<=MPD( PracticallyMinusInfty() ) ?
Context::CTX_NEG : con.ub()>=MPD( PracticallyInfty() ) ?
auto ctx = con.lb()<=MPD( PracticallyMinusInf() ) ?
Context::CTX_NEG : con.ub()>=MPD( PracticallyInf() ) ?
Context::CTX_POS : Context::CTX_MIX;
PropagateResult2Args(con.GetBody(), con.lb(), con.ub(), ctx);
}
Expand Down
36 changes: 32 additions & 4 deletions include/mp/flat/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "mp/flat/constr_prop_down.h"
#include "mp/valcvt.h"
#include "mp/flat/redef/std/range_con.h"
#include "mp/flat/redef/conic/cones.h"
#include "mp/utils-file.h"

namespace mp {
Expand Down Expand Up @@ -166,9 +167,10 @@ class FlatConverter :
//////////////////////////// THE CONVERSION LOOP: BREADTH-FIRST ///////////////////////
void ConvertItems() {
try {
MPD( Convert2Cones(); ); // sweep before other conversions
MP_DISPATCH( ConvertAllConstraints() );
// MP_DISPATCH( PreprocessIntermediate() ); // preprocess after each level
MP_DISPATCH( ConvertMaps() );
MP_DISPATCH( ConvertMaps() );
MP_DISPATCH( PreprocessFinal() ); // final prepro
} catch (const ConstraintConversionFailure& cff) {
MP_RAISE(cff.message());
Expand All @@ -183,6 +185,11 @@ class FlatConverter :
}
}

/// Offload the conic logic to a functor
void Convert2Cones() {
conic_cvt_.Run();
}

void ConvertAllConstraints() {
GetModel().ConvertAllConstraints(*this);
}
Expand Down Expand Up @@ -664,6 +671,14 @@ class FlatConverter :
return ModelAPI::AcceptsNonconvexQC();
}

/// Whether the ModelAPI accepts quadragtic cones
int ModelAPIAcceptsQuadraticCones() {
return
std::max(
(int)GetConstraintAcceptance((QuadraticConeConstraint*)nullptr),
(int)GetConstraintAcceptance((RotatedQuadraticConeConstraint*)nullptr));
}


private:
struct Options {
Expand All @@ -673,8 +688,8 @@ class FlatConverter :
int preprocessEqualityBvar_ = 1;

int passQuadObj_ = ModelAPIAcceptsQuadObj();
int passQuadCon_ = ModelAPIAcceptsQC();

int passQuadCon_ = ModelAPIAcceptsQC();
int passQuadCones_ = 0;

int relax_ = 0;
};
Expand Down Expand Up @@ -731,7 +746,14 @@ class FlatConverter :
"0*/1: Multiply out and pass quadratic constraint terms to the solver, "
"vs. linear approximation.",
options_.passQuadCon_, 0, 1);
GetEnv().AddOption("alg:relax relax",
if (ModelAPIAcceptsQuadraticCones())
GetEnv().AddOption("cvt:socp passsocp socp",
ModelAPIAcceptsQuadraticCones()>1 ?
"0/1*: Recognize quadratic cones." :
"0*/1: Recognize quadratic cones.",
options_.passQuadCones_, 0, 1);
options_.passQuadCones_ = ModelAPIAcceptsQuadraticCones()>1;
GetEnv().AddOption("alg:relax relax",
"0*/1: Whether to relax integrality of variables.",
options_.relax_, 0, 1);
}
Expand Down Expand Up @@ -765,6 +787,9 @@ class FlatConverter :
bool IfQuadratizePowConstPosIntExp() const
{ return options_.passQuadCon_; }

/// Whether we pass quad cones
bool IfPassQuadCones() const { return options_.passQuadCon_; }


public:
/// Typedef ModelAPIType. For tests
Expand Down Expand Up @@ -798,6 +823,8 @@ class FlatConverter :
pre::NodeRange auto_link_src_item_; // the source item for autolinking
std::vector<pre::NodeRange> auto_link_targ_items_;

ConicConverter<Impl> conic_cvt_ { *static_cast<Impl*>(this) };


protected:
/////////////////////// CONSTRAINT KEEPERS /////////////////////////
Expand Down Expand Up @@ -904,6 +931,7 @@ class FlatConverter :
RotatedQuadraticConeConstraint, "acc:rotatedquadcone")


protected:
////////////////////// Default map accessors /////////////////////////
/// Constraints without map should overload these by empty methods ///

Expand Down
3 changes: 3 additions & 0 deletions include/mp/flat/model_api_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,17 @@ class BasicFlatModelAPI {
using BaseBackend::AddConstraint; \
using BaseBackend::AcceptanceLevel; \
using BaseBackend::GroupNumber;

/// Default constraint group
static constexpr ConstraintGroup GroupNumber(const BasicConstraint*) {
return CG_Default;
}

/// By default, we say constraint XYZ is not accepted but...
static constexpr ConstraintAcceptanceLevel AcceptanceLevel(const BasicConstraint*) {
return NotAccepted;
}

/// Specifically, ask if the solver accepts non-convex quadratic constraints
static constexpr bool AcceptsNonconvexQC() { return false; }

Expand Down
2 changes: 1 addition & 1 deletion include/mp/flat/redef/MIP/indicator_ge.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class IndicatorLinGEConverter_MIP :
/// Linearize (b==val ==> c'x>=d) via big-M
void ConvertImplicationGE(int b, int val,
double body_lb, LinConGE con) {
if (body_lb <= GetMC().PracticallyMinusInfty()) {
if (body_lb <= GetMC().PracticallyMinusInf()) {
if ( (body_lb = -GetMC().bigMDefault())>=0.0 )
throw ConstraintConversionFailure( "IndicatorInfBound",
"The redefinition of an indicator constraint"
Expand Down
2 changes: 1 addition & 1 deletion include/mp/flat/redef/MIP/indicator_le.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class IndicatorLinLEConverter_MIP :
double body_ub, LinConLE con) {
/// TODO fail if lb>0 +report .iis if requested
/// TODO skip if ub<0
if (body_ub >= GetMC().PracticallyInfty()) {
if (body_ub >= GetMC().PracticallyInf()) {
if ((body_ub = GetMC().bigMDefault())<=0.0)
throw ConstraintConversionFailure( "IndicatorInfBound",
"The redefinition of an indicator constraint"
Expand Down
38 changes: 3 additions & 35 deletions include/mp/flat/redef/MIP/mul.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,50 +27,18 @@ class QCConverter_MIP :
/// Check whether the constraint
/// needs to be converted despite being accepted by ModelAPI.
bool IfNeedsConversion(const ItemType& , int ) {
return IfCvtAcceptsQPCones() ||
!GetMC().IfPassQuadCon();
return !GetMC().IfPassQuadCon();
}

/// Conversion
void Convert(const ItemType& qc, int i) {
if (IfCvtAcceptsQPCones() && // conex accepted
GetMC().IfPassQuadCon()) // passing quadratic to solver, incl. cones
TryConvertToCone(qc, i);
else
LinearizeQPTerms(qc);
void Convert(const ItemType& qc, int ) {
LinearizeQPTerms(qc);
}


protected:
using Base::GetMC;

bool IfCvtAcceptsQPCones() {
return
GetMC().GetConstraintAcceptance((QuadraticConeConstraint*)nullptr) ||
GetMC().GetConstraintAcceptance((RotatedQuadraticConeConstraint*)nullptr);
}

void TryConvertToCone(const ItemType& qc, int ) {
if (!TryQuadCone(qc) && !TryRotatedQuadCone(qc))
throw ConstraintConversionGracefulFailure();
}

bool TryQuadCone(const ItemType& qc) {
if (GetMC().GetConstraintAcceptance(
(QuadraticConeConstraint*)nullptr)) {
return true;
}
return false;
}

bool TryRotatedQuadCone(const ItemType& qc) {
if (GetMC().GetConstraintAcceptance(
(RotatedQuadraticConeConstraint*)nullptr)) {
return true;
}
return false;
}

void LinearizeQPTerms(const ItemType& qc) {
const auto& body = qc.GetBody();
// Copy lin terms
Expand Down
Loading

0 comments on commit b2b5d41

Please sign in to comment.