1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
|
////////////////////////////////////////////////////////////////////////////////
//
// RegularityCheck.hh
//
// produced: 2001/10/20 jr
// last change: 2001/10/20 jr
//
////////////////////////////////////////////////////////////////////////////////
#ifndef REGULARITYCHECK_HH
#define REGULARITYCHECK_HH
#include <thread>
#include <mutex>
#include "Vector.hh"
#include "Matrix.hh"
#include "PointConfiguration.hh"
#include "LabelSet.hh"
#include "SimplicialComplex.hh"
#include "Flip.hh"
#include "CommandlineOptions.hh"
#include "Chirotope.hh"
#include "Incidences.hh"
#include "LPinterface.hh"
#include "SPXinterface.hh"
#ifdef USE_QSO
#include "QSOinterface.hh"
#endif
namespace topcom {
#ifdef REGULARITY_CACHE
typedef std::pair<Simplex, Simplex> constraint_conf_type;
class ConstraintCacheEntry : public constraint_conf_type {
public:
inline ConstraintCacheEntry() = delete;
inline ConstraintCacheEntry(const Simplex& unionsimp, const Simplex& intersection) :
constraint_conf_type(unionsimp, intersection) {}
public:
size_type keysize() const { return 2; }
size_type key(const size_type n) const {
if (n == 0) {
return first.key(0);
}
else {
return second.key(0);
}
}
};
typedef std::unordered_map<ConstraintCacheEntry, Vector, Hash<ConstraintCacheEntry> > constraint_cache_data;
class ConstraintCache : public constraint_cache_data {
};
#endif
class RegularityCheck {
public:
static size_type cnt_calls;
private:
Vector _heights;
Matrix _coeffs;
const PointConfiguration* _pointsptr;
const Chirotope* _chiroptr;
const SimplicialComplex* _triangptr;
const Incidences* _incidencesptr;
#ifdef REGULARITY_CACHE
private:
// thread-local caching (map a union of two simplices and their common face
// to the coefficients of the corresponding folding form:
static ConstraintCache _cache;
#endif
private:
// multithreading:
static std::mutex _reg_mutex;
private:
RegularityCheck() = delete;
public:
// constructors:
RegularityCheck(const PointConfiguration&,
const Chirotope&,
const Incidences&,
const SimplicialComplex&);
inline RegularityCheck(const RegularityCheck&);
inline RegularityCheck(const RegularityCheck&, const Flip&);
// destructor:
inline ~RegularityCheck();
// assignments:
inline RegularityCheck& operator=(const RegularityCheck&);
// accessors:
inline const Vector heights() const { return _heights; }
inline const Matrix coeffs() const { return _coeffs; }
inline const Chirotope* chiroptr() const { return _chiroptr; }
// init/term the solver:
inline static void init();
inline static void term();
// functions:
inline const bool is_regular(); // changes "_heights"
};
// constructors:
inline RegularityCheck::RegularityCheck(const RegularityCheck&) {
std::cerr << "RegularityCheck::RegularityCheck(const RegularityCheck&): not yet implemented!" << std::endl;
}
inline RegularityCheck::RegularityCheck(const RegularityCheck&, const Flip&){
std::cerr << "RegularityCheck::RegularityCheck(const RegularityCheck&, const Flip&): not yet implemented!" << std::endl;
}
// destructor:
inline RegularityCheck::~RegularityCheck() {
#ifdef CONSTRUCTOR_DEBUG
std::cerr << "destroying coefficients of RegularityCheck " << this->_coeffs << std::endl;
#endif
}
// assignment:
inline RegularityCheck& RegularityCheck::operator=(const RegularityCheck& rc) {
if (this == &rc) {
return *this;
}
_heights = rc._heights;
_coeffs = rc._coeffs;
_pointsptr = rc._pointsptr;
_chiroptr = rc._chiroptr;
_triangptr = rc._triangptr;
_incidencesptr = rc._incidencesptr;
return *this;
}
// functions:
inline const bool RegularityCheck::is_regular() {
{
std::lock_guard<std::mutex> lock(_reg_mutex);
++cnt_calls;
}
// do not interrupt computation because user may want heights!
// if (_chiroptr->rank() < 3) {
// return true;
// }
if (_coeffs.coldim() == 0) {
if (CommandlineOptions::output_heights()) {
// take a height vector that is ZERO on all used points and ONE otherwise:
const LabelSet support(_triangptr->support());
const parameter_type no(_chiroptr->no());
for (size_type i = 0; i < no; ++i) {
if (!support.contains(i)) {
_heights.at(i) = FieldConstants::ONE;
}
}
}
return true;
}
#ifdef HAVE_LIBSOPLEX
if (CommandlineOptions::use_soplex()) {
SPXinterface LP(_coeffs, _triangptr->support());
const bool regular(LP.has_interior_point(&_heights));
if (CommandlineOptions::debug()) {
LPinterface LP(_coeffs, _triangptr->support());
const bool double_check_regular(LP.has_interior_point(&_heights));
if (regular != double_check_regular) {
std::cerr << "RegularityCheck::is_regular() const: wrong result, exiting;" << std::endl
<< "please inspect soplex.lp." << std::endl;
exit(1);
}
}
return regular;
}
else {
#endif
#ifdef USE_QSO
if (CommandlineOptions::use_qsopt_ex()) {
// qsopt_ex cannot run in a multi-threaded environment
// because of its memory management(?);
// even locking does not suffice,
// thus parallel enumeration is
// not supported with qsopt_ex from the start:
QSOinterface LP(_coeffs, _triangptr->support());
const bool result = LP.has_interior_point(&_heights);
return result;
}
else
#endif
{
// with the patched version of cddlib with TLS
// we can run the cdd lp solver lock-free:
LPinterface LP(_coeffs, _triangptr->support());
const bool result = LP.has_interior_point(&_heights);
return result;
}
#ifdef HAVE_LIBSOPLEX
}
#endif
}
// init/term the solver:
inline void RegularityCheck::init() {
#ifdef USE_QSO
if (CommandlineOptions::use_qsopt_ex()) {
QSOinterface::init();
}
else
#endif
#ifdef HAVE_LIBSOPLEX
if (CommandlineOptions::use_soplex()) {
SPXinterface::init();
} else
#endif
{
LPinterface::init();
}
}
inline void RegularityCheck::term() {
#if USE_QSO
if (CommandlineOptions::use_qsopt_ex()) {
QSOinterface::term();
}
else
#endif
#ifdef HAVE_LIBSOPLEX
if (CommandlineOptions::use_soplex()) {
SPXinterface::term();
}
else
#endif
{
LPinterface::term();
}
if (CommandlineOptions::verbose()) {
std::lock_guard<std::mutex> lock(IO_sync::mutex);
std::cerr << cnt_calls << " calls of RegularityCheck in total" << std::endl;
}
}
}; // namespace topcom
#endif
// eof RegularityCheck.hh
|