1 /** 2 * 3 * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(_at_LIP6) & Christophe GONZALES(_at_AMU) 4 * info_at_agrum_dot_org 5 * 6 * This library is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public License 17 * along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 22 #include <string.h> 23 24 #include <agrum/CN/polytope/LrsWrapper.h> 25 #include <agrum/agrum.h> 26 27 namespace gum { 28 namespace credal { 29 30 template < typename GUM_SCALAR > LRSWrapper()31 LRSWrapper< GUM_SCALAR >::LRSWrapper() { 32 _state_ = _states_::none; 33 34 _vertices_ = 0; 35 _card_ = 0; 36 37 _volume_ = 0; 38 39 _getVolume_ = false; 40 _hull_ = false; 41 _polytope_ = false; 42 43 GUM_CONSTRUCTOR(LRSWrapper); 44 } 45 46 template < typename GUM_SCALAR > ~LRSWrapper()47 LRSWrapper< GUM_SCALAR >::~LRSWrapper() { 48 GUM_DESTRUCTOR(LRSWrapper); 49 } 50 51 template < typename GUM_SCALAR > 52 auto LRSWrapper< GUM_SCALAR >::getInput() const -> const matrix& { 53 return _input_; 54 } 55 56 template < typename GUM_SCALAR > 57 auto LRSWrapper< GUM_SCALAR >::getOutput() const -> const matrix& { 58 return _output_; 59 } 60 61 template < typename GUM_SCALAR > getVerticesNumber()62 const unsigned int& LRSWrapper< GUM_SCALAR >::getVerticesNumber() const { 63 return _vertices_; 64 } 65 66 template < typename GUM_SCALAR > getVolume()67 const GUM_SCALAR& LRSWrapper< GUM_SCALAR >::getVolume() const { 68 if (_volume_ != 0) 69 return _volume_; 70 else 71 GUM_ERROR(OperationNotAllowed, 72 "LRSWrapper< GUM_SCALAR >::getVolume () : " 73 "volume computation was not asked for this " 74 "credal set, call computeVolume() from a " 75 "V-representation."); 76 } 77 78 template < typename GUM_SCALAR > setUpH(const Size & card)79 void LRSWrapper< GUM_SCALAR >::setUpH(const Size& card) { 80 if (card < 2) 81 GUM_ERROR(OperationNotAllowed, 82 "LRSWrapper< GUM_SCALAR >::setUpH : " 83 "cardinality must be at least 2"); 84 85 tearDown(); 86 87 _input_ = std::vector< std::vector< GUM_SCALAR > >(card * 2 + 2, 88 std::vector< GUM_SCALAR >(card + 1, 0)); 89 90 _input_[card * 2] = std::vector< GUM_SCALAR >(card + 1, -1); 91 _input_[card * 2][0] = 1; 92 93 _input_[card * 2 + 1] = std::vector< GUM_SCALAR >(card + 1, 1); 94 _input_[card * 2 + 1][0] = -1; 95 96 _output_ = std::vector< std::vector< GUM_SCALAR > >(); 97 98 _vertex_ = std::vector< GUM_SCALAR >(card); 99 100 _state_ = _states_::Hup; 101 102 _card_ = (unsigned int)card; 103 } 104 105 template < typename GUM_SCALAR > setUpV(const Size & card,const Size & vertices)106 void LRSWrapper< GUM_SCALAR >::setUpV(const Size& card, const Size& vertices) { 107 if (card < 2) 108 GUM_ERROR(OperationNotAllowed, 109 "LRSWrapper< GUM_SCALAR >::setUpV : " 110 "cardinality must be at least 2"); 111 112 if (vertices < 2) 113 GUM_ERROR(OperationNotAllowed, 114 "LRSWrapper< GUM_SCALAR >::setUpV : vertices " 115 "must be at least 2 to build a polytope"); 116 117 tearDown(); 118 119 _input_ = std::vector< std::vector< GUM_SCALAR > >(vertices, 120 std::vector< GUM_SCALAR >(card + 1, 1)); 121 122 _output_ = std::vector< std::vector< GUM_SCALAR > >(); 123 124 _state_ = _states_::Vup; 125 126 _card_ = (unsigned int)card; 127 _vertices_ = (unsigned int)vertices; 128 } 129 130 template < typename GUM_SCALAR > tearDown()131 void LRSWrapper< GUM_SCALAR >::tearDown() { 132 _input_.clear(); 133 _output_.clear(); 134 _vertex_.clear(); 135 _insertedModals_.clear(); 136 137 _insertedVertices_.clear(); 138 _vertices_ = 0; 139 140 _volume_ = 0; 141 142 _state_ = _states_::none; 143 _card_ = 0; 144 145 _getVolume_ = false; 146 _hull_ = false; 147 _polytope_ = false; 148 } 149 150 template < typename GUM_SCALAR > nextHInput()151 void LRSWrapper< GUM_SCALAR >::nextHInput() { 152 _insertedModals_.clear(); 153 _insertedVertices_.clear(); 154 _output_.clear(); 155 _vertex_.clear(); 156 _vertex_.resize(_card_, 0); 157 158 _volume_ = 0; 159 _vertices_ = 0; 160 161 _getVolume_ = false; 162 _hull_ = false; 163 _polytope_ = false; 164 165 if (_state_ == _states_::H2Vready) 166 _state_ = _states_::Hup; 167 else if (_state_ == _states_::V2Hready) { 168 _state_ = _states_::Vup; 169 GUM_ERROR(OperationNotAllowed, 170 "LRSWrapper< GUM_SCALAR >::nextHInput : only for H-representation " 171 "as input. Previous state was : " 172 << _setUpStateNames_[static_cast< int >(_state_)]); 173 } else { 174 _input_.clear(); 175 _state_ = _states_::none; 176 _card_ = 0; 177 _vertex_.clear(); 178 } 179 } 180 181 template < typename GUM_SCALAR > fillH(const GUM_SCALAR & min,const GUM_SCALAR & max,const Size & modal)182 void LRSWrapper< GUM_SCALAR >::fillH(const GUM_SCALAR& min, 183 const GUM_SCALAR& max, 184 const Size& modal) { 185 if (_state_ != _states_::Hup) 186 GUM_ERROR(OperationNotAllowed, 187 "LRSWrapper< GUM_SCALAR >::fillH : setUpH or nextInput has not " 188 "been called or H-representation is complete, current state is : " 189 << _setUpStateNames_[static_cast< int >(_state_)]); 190 191 if (modal >= _card_) 192 GUM_ERROR(OutOfBounds, 193 "LRSWrapper< GUM_SCALAR >::fillH : modality is " 194 "greater or equal than cardinality : " 195 << modal << " >= " << _card_); 196 197 _input_[modal * 2][0] = -min; 198 _input_[modal * 2][modal + 1] = 1; 199 200 _input_[modal * 2 + 1][0] = max; 201 _input_[modal * 2 + 1][modal + 1] = -1; 202 203 _vertex_[modal] = max; 204 205 _insertedModals_.insert(int(modal)); 206 207 if (_insertedModals_.size() == _card_) _state_ = _states_::H2Vready; 208 } 209 210 template < typename GUM_SCALAR > fillMatrix(const std::vector<std::vector<GUM_SCALAR>> & matrix)211 void LRSWrapper< GUM_SCALAR >::fillMatrix( 212 const std::vector< std::vector< GUM_SCALAR > >& matrix) { 213 if (_state_ != _states_::Hup) 214 GUM_ERROR(OperationNotAllowed, 215 "LRSWrapper< GUM_SCALAR >::fillH : setUpH or nextInput has not " 216 "been called or H-representation is complete, current state is : " 217 << _setUpStateNames_[static_cast< int >(_state_)]); 218 219 if (matrix[0].size() - 1 != _card_) 220 GUM_ERROR(OutOfBounds, 221 "LRSWrapper< GUM_SCALAR >::fillMatrix : size is " 222 "different than cardinality : " 223 << (matrix[0].size() - 1) << " != " << _card_); 224 225 _input_ = matrix; 226 227 for (unsigned int modal = 0; modal < _card_; modal++) { 228 _insertedModals_.insert(modal); 229 } 230 231 _state_ = _states_::H2Vready; 232 } 233 234 template < typename GUM_SCALAR > fillV(const std::vector<GUM_SCALAR> & vertex)235 void LRSWrapper< GUM_SCALAR >::fillV(const std::vector< GUM_SCALAR >& vertex) { 236 if (_state_ != _states_::Vup) 237 GUM_ERROR(OperationNotAllowed, 238 "LRSWrapper< GUM_SCALAR >::fillV : setUpV or nextInput has not " 239 "been called or V-representation is complete, current state is : " 240 << _setUpStateNames_[static_cast< int >(_state_)]); 241 242 if (_insertedVertices_.size() == _vertices_) 243 GUM_ERROR(OutOfBounds, 244 "LRSWrapper< GUM_SCALAR >::fillV : input is already full with " << _vertices_ 245 << " vertices."); 246 247 bool eq = true; 248 249 for (const auto& v: _insertedVertices_) { 250 eq = true; 251 252 for (decltype(_card_) mod = 0; mod < _card_; mod++) 253 if (std::fabs(v[mod] - vertex[mod]) > 1e-6) { 254 eq = false; 255 break; 256 } 257 258 if (eq) { 259 _vertices_--; 260 return; 261 // GUM_ERROR ( DuplicateElement, "LRSWrapper< GUM_SCALAR >::fillV : 262 // vertex 263 // already present : " << vertex ); 264 } 265 } 266 267 auto row = _insertedVertices_.size(); 268 269 for (decltype(_card_) mod = 0; mod < _card_; mod++) 270 _input_[row][mod + 1] = vertex[mod]; 271 272 _insertedVertices_.push_back(vertex); 273 274 if (_insertedVertices_.size() == _vertices_) _state_ = _states_::V2Hready; 275 } 276 277 template < typename GUM_SCALAR > H2V()278 void LRSWrapper< GUM_SCALAR >::H2V() { 279 if (_state_ != _states_::H2Vready) 280 GUM_ERROR(OperationNotAllowed, 281 "LRSWrapper< GUM_SCALAR >::H2V : fillH has not been called with " 282 "all modalities, current state is still : " 283 << _setUpStateNames_[static_cast< int >(_state_)]); 284 285 // check that we have a credal set and not a precise point probability, 286 // i.e. 287 // sum of vertex elements is close to one ( floating type precision ) 288 GUM_SCALAR sum = 0; 289 290 for (const auto elem: _vertex_) 291 sum += elem; 292 293 if (std::fabs(sum - 1) < 1e-6) { 294 _output_ = std::vector< std::vector< GUM_SCALAR > >(1, _vertex_); 295 return; 296 } 297 298 // not precise point probability, initialize lrs 299 300 // _coutOff_(); 301 302 _initLrs_(); 303 304 /* We initiate reverse search from this dictionary */ 305 /* getting new dictionaries until the search is complete */ 306 /* User can access each output line from output which is */ 307 /* vertex/ray/facet from the lrs_mp_vector output */ 308 /* prune is TRUE if tree should be pruned at current node */ 309 310 // pruning is not used 311 312 std::vector< int64_t > Num; /* numerators of all vertices */ 313 std::vector< int64_t > Den; /* denominators of all vertices */ 314 315 do { 316 for (decltype(_dic_->d) col = 0, end = _dic_->d; col <= end; col++) 317 if (lrs_getsolution(_dic_, _dat_, _lrsOutput_, col)) { 318 // iszero macro could be used here for the test on right 319 if (_dat_->hull 320 || ((((_lrsOutput_[0])[0] == 2 || (_lrsOutput_[0])[0] == -2) 321 && (_lrsOutput_[0])[1] == 0) 322 ? 1L 323 : 0L)) { 324 // _coutOn_(); 325 /*for ( decltype(Q->n) i = 0; i < Q->n; i++ ) 326 pmp ("", output[i]);*/ 327 GUM_ERROR(FatalError, 328 "LRSWrapper< GUM_SCALAR >::H2V : asked for " 329 "Q-hull computation or not reading a vertex !"); 330 } else 331 for (decltype(_dat_->n) i = 1, end = _dat_->n; i < end; i++) 332 _getLRSWrapperOutput_(_lrsOutput_[i], _lrsOutput_[0], Num, Den); 333 } 334 } while (lrs_getnextbasis(&_dic_, _dat_, 0L)); 335 336 auto vtx = Num.size(); 337 std::vector< GUM_SCALAR > vertex(_card_); 338 339 for (decltype(vtx) i = 1; i <= vtx; i++) { 340 vertex[(i - 1) % _card_] = GUM_SCALAR(Num[i - 1] * 1.0 / Den[i - 1]); 341 342 if (i % _card_ == 0) { 343 _output_.push_back(vertex); 344 _vertices_++; 345 } 346 } 347 348 _freeLrs_(); 349 350 // _coutOn_(); 351 } 352 353 template < typename GUM_SCALAR > V2H()354 void LRSWrapper< GUM_SCALAR >::V2H() { 355 if (!_state_ == _states_::V2Hready) 356 GUM_ERROR(OperationNotAllowed, 357 "LRSWrapper< GUM_SCALAR >::V2H : fillV has " 358 "not been called with all vertices, current " 359 "state is still : " 360 << _setUpStateNames_[_state_]); 361 } 362 363 template < typename GUM_SCALAR > computeVolume()364 void LRSWrapper< GUM_SCALAR >::computeVolume() { 365 if (!_state_ == _states_::V2Hready) 366 GUM_ERROR(OperationNotAllowed, 367 "LRSWrapper< GUM_SCALAR >::computeVolume : " 368 "volume is only for V-representation or " 369 "fillV has not been called with all " 370 "vertices, current state is still : " 371 << _setUpStateNames_[_state_]); 372 373 // _coutOff_(); 374 375 _getVolume_ = true; 376 377 _initLrs_(); 378 379 do { 380 for (decltype(_dic_->d) col = 0, end = _dic_->d; col <= end; col++) 381 lrs_getsolution(_dic_, _dat_, _lrsOutput_, col); 382 } while (lrs_getnextbasis(&_dic_, _dat_, 0L)); 383 384 int64_t Nsize = (_dat_->Nvolume[0] > 0) ? _dat_->Nvolume[0] : -_dat_->Nvolume[0]; 385 int64_t Dsize = (_dat_->Dvolume[0] > 0) ? _dat_->Dvolume[0] : -_dat_->Dvolume[0]; 386 387 int64_t num = 0L, den = 0L; 388 int64_t tmp; 389 390 for (decltype(Nsize) i = Nsize - 1; i > 0; i--) { 391 tmp = _dat_->Nvolume[i]; 392 393 for (decltype(i) j = 1; j < i; j++) 394 tmp *= BASE; 395 396 num += tmp; 397 } 398 399 for (decltype(Dsize) i = Dsize - 1; i > 0; i--) { 400 tmp = _dat_->Dvolume[i]; 401 402 for (decltype(i) j = 1; j < i; j++) 403 tmp *= BASE; 404 405 den += tmp; 406 } 407 408 _volume_ = num * 1.0 / den; 409 410 _freeLrs_(); 411 412 // _coutOn_(); 413 } 414 415 template < typename GUM_SCALAR > elimRedundVrep()416 void LRSWrapper< GUM_SCALAR >::elimRedundVrep() { 417 if (_state_ != _states_::V2Hready) 418 GUM_ERROR(OperationNotAllowed, 419 "LRSWrapper< GUM_SCALAR >::elimRedundVrep : only for " 420 "V-representation or fillV has not been called with all vertices, " 421 "current state is still : " 422 << _setUpStateNames_[static_cast< int >(_state_)]); 423 424 // _coutOff_(); 425 426 _initLrs_(); 427 428 int64_t* redineq; /* redineq[i]=0 if ineq i non-red,1 if red,2 linearity */ 429 430 /*********************************************************************************/ 431 /* Test each row of the dictionary to see if it is redundant */ 432 /*********************************************************************************/ 433 434 /* note some of these may have been changed in getting initial dictionary 435 */ 436 auto m = _dic_->m_A; 437 auto d = _dic_->d; 438 /* number of linearities in input */ /* should be 0 ! */ 439 auto nlinearity = _dat_->nlinearity; 440 auto lastdv = _dat_->lastdv; 441 442 /* linearities are not considered for redundancy */ 443 redineq = (int64_t*)calloc(std::size_t(m + 1), sizeof(int64_t)); 444 445 for (decltype(nlinearity) i = 0; i < nlinearity; i++) 446 redineq[_dat_->linearity[i]] = 2L; 447 448 /* rows 0..lastdv are cost, decision variables, or linearities */ 449 /* other rows need to be tested */ 450 451 for (decltype(m + d) index = lastdv + 1, end = m + d; index <= end; index++) { 452 /* input inequality number of current index */ 453 auto ineq = _dat_->inequality[index - lastdv]; /* the input inequality number 454 corr. to this index */ 455 456 redineq[ineq] = checkindex(_dic_, _dat_, index); 457 } 458 459 /* linearities */ 460 if (nlinearity > 0) 461 GUM_ERROR(FatalError, 462 "LRSWrapper< GUM_SCALAR >::elimRedundVrep : not " 463 "reading a vertex but a linearity !"); 464 465 /* count number of non-redundant inequalities */ 466 /* 467 auto nredund = nlinearity; 468 for ( decltype ( m ) i = 1; i <= m; i++ ) 469 if ( redineq[ i ] == 0 ) 470 nredund++; 471 */ 472 473 // __vertices = nredund; 474 // __output = std::vector< std::vector< GUM_SCALAR > > ( nredund, 475 // std::vector< 476 // GUM_SCALAR > ( _dat_->n - 1 ) ); 477 478 for (decltype(m) i = 1; i <= m; i++) 479 if (redineq[i] == 0) 480 _output_.push_back(std::vector< GUM_SCALAR >(++_input_[std::size_t(i - 1)].begin(), 481 _input_[std::size_t(i - 1)].end())); 482 483 _vertices_ = (unsigned int)_output_.size(); 484 485 _freeLrs_(); 486 487 // _coutOn_(); 488 } 489 490 template < typename GUM_SCALAR > _getLRSWrapperOutput_(lrs_mp Nin,lrs_mp Din,std::vector<int64_t> & Num,std::vector<int64_t> & Den)491 void LRSWrapper< GUM_SCALAR >::_getLRSWrapperOutput_(lrs_mp Nin, 492 lrs_mp Din, 493 std::vector< int64_t >& Num, 494 std::vector< int64_t >& Den) const { 495 int64_t Nsize = (Nin[0] > 0) ? Nin[0] : -Nin[0]; 496 int64_t Dsize = (Din[0] > 0) ? Din[0] : -Din[0]; 497 498 int64_t num = 0L; 499 int64_t den = 0L; 500 501 int64_t tmp; 502 503 for (decltype(Nsize) i = Nsize - 1; i > 0; i--) { 504 tmp = Nin[i]; 505 506 for (decltype(i) j = 1; j < i; j++) 507 tmp *= BASE; 508 509 num += tmp; 510 } 511 512 if (!(Din[0] == 2L && Din[1] == 1L)) { /* rational */ 513 for (decltype(Dsize) i = Dsize - 1; i > 0; i--) { 514 tmp = Din[i]; 515 516 for (decltype(i) j = 1; j < i; j++) 517 tmp *= BASE; 518 519 den += tmp; 520 } 521 } else { 522 den = 1L; 523 } 524 525 int64_t Nsign = ((Nin[0] < 0) ? -1L : 1L); 526 int64_t Dsign = ((Din[0] < 0) ? -1L : 1L); 527 528 if ((Nsign * Dsign) == -1L) num = -num; 529 530 Num.push_back(num); 531 Den.push_back(den); 532 } 533 534 /* 535 void pmp (char name[], lrs_mp a) { 536 int64_t i; 537 fprintf (lrs_ofp, "%s", name); 538 if (sign (a) == NEG) 539 fprintf (lrs_ofp, "-"); 540 else 541 fprintf (lrs_ofp, " "); 542 fprintf (lrs_ofp, "%lu", a[length (a) - 1]); 543 for (i = length (a) - 2; i >= 1; i--) 544 fprintf (lrs_ofp, FORMAT, a[i]); 545 fprintf (lrs_ofp, " "); 546 }*/ 547 548 template < typename GUM_SCALAR > _fill_()549 void LRSWrapper< GUM_SCALAR >::_fill_() const { 550 std::size_t cols = _input_[0].size(); 551 552 int64_t* num = new int64_t[cols]; // ISO C++ forbids variable length array, 553 // we need to do this instead 554 int64_t* den = new int64_t[cols]; 555 556 int64_t rows = int64_t(_input_.size()); 557 558 int64_t numerator, denominator; 559 560 for (int64_t row = 0; row < rows; row++) { 561 for (std::size_t col = 0; col < cols; col++) { 562 Rational< GUM_SCALAR >::continuedFracFirst(numerator, 563 denominator, 564 _input_[std::size_t(row)][col]); 565 566 num[col] = numerator; 567 den[col] = denominator; 568 } 569 570 /* GE is inequality, EQ is equation */ 571 /* 1L, 0L respectively */ 572 lrs_set_row(_dic_, 573 _dat_, 574 int64_t(row + 1), 575 num, 576 den, 577 1L); // do NOT forget this + 1 on row 578 } 579 580 delete[] num; 581 delete[] den; 582 } 583 584 template < typename GUM_SCALAR > _initLrs_()585 void LRSWrapper< GUM_SCALAR >::_initLrs_() { 586 if (_state_ != _states_::H2Vready && _state_ != _states_::V2Hready) 587 GUM_ERROR(OperationNotAllowed, 588 "LRSWrapper< GUM_SCALAR >:: _initLrs_ : not ready, current state " 589 "is still : " 590 << _setUpStateNames_[static_cast< int >(_state_)]); 591 592 // __coutOff(); 593 594 std::string name = "\n*LrsWrapper:"; 595 std::vector< char > chars(name.c_str(), name.c_str() + name.size() + 1u); 596 // use &chars[0] as a char* 597 598 if (!lrs_init(&chars[0])) { 599 // _coutOn_(); 600 GUM_ERROR(FatalError, "LRSWrapper< GUM_SCALAR >:: _initLrs_ : failed lrs_init") 601 } 602 603 name = "LRSWrapper globals"; 604 chars = std::vector< char >(name.c_str(), name.c_str() + name.size() + 1u); 605 606 _dat_ = lrs_alloc_dat(&chars[0]); 607 608 if (_dat_ == nullptr) { 609 // _coutOn_(); 610 GUM_ERROR(FatalError, "LRSWrapper< GUM_SCALAR >:: _initLrs_ : failed lrs_alloc_dat") 611 } 612 613 _dat_->n = Size(_input_[0].size()); 614 _dat_->m = Size(_input_.size()); 615 616 _dat_->getvolume = (_getVolume_) ? 1L : 0L; 617 _dat_->hull = (_hull_) ? 1L : 0L; 618 _dat_->polytope = (_polytope_) ? 1L : 0L; 619 620 _lrsOutput_ = lrs_alloc_mp_vector(_dat_->n); 621 622 _dic_ = lrs_alloc_dic(_dat_); 623 624 if (_dic_ == nullptr) { 625 // _coutOn_(); 626 GUM_ERROR(FatalError, "LRSWrapper< GUM_SCALAR >:: _initLrs_ : failed lrs_alloc_dic") 627 } 628 629 _fill_(); 630 631 /* Pivot to a starting dictionary */ 632 if (!lrs_getfirstbasis(&_dic_, _dat_, &_Lin_, 0L)) { 633 // _coutOn_(); 634 GUM_ERROR(FatalError, "LRSWrapper< GUM_SCALAR >:: _initLrs_ : failed lrs_getfirstbasis"); 635 } 636 637 /* There may have been column redundancy */ 638 /* If so the linearity space is obtained and redundant */ 639 /* columns are removed. User can access linearity space */ 640 /* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ 641 642 decltype(_dat_->nredundcol) startcol = 0; 643 644 if (_dat_->homogeneous && _dat_->hull) { 645 startcol++; /* col zero not treated as redundant */ 646 647 if (!_dat_->restart) { 648 // _coutOn_(); 649 650 for (decltype(_dat_->nredundcol) col = startcol; col < _dat_->nredundcol; col++) 651 lrs_printoutput(_dat_, _Lin_[col]); 652 653 GUM_ERROR(FatalError, "LRSWrapper< GUM_SCALAR >:: _initLrs_ : redundant columns !") 654 } 655 } 656 /* 657 if ( _dat_->nredundcol > 0 ) { 658 _coutOn_(); 659 660 for ( decltype( _dat_->nredundcol ) col = 0, end = 661 _dat_->nredundcol; 662 col < end; 663 col++ ) 664 lrs_printoutput( _dat_, _Lin_[col] ); 665 666 GUM_ERROR( 667 FatalError, 668 "LRSWrapper< GUM_SCALAR >:: _initLrs_ : redundant columns !" ); 669 } 670 */ 671 } 672 673 template < typename GUM_SCALAR > _freeLrs_()674 void LRSWrapper< GUM_SCALAR >::_freeLrs_() { 675 /* free space : do not change order of next lines! */ 676 677 lrs_clear_mp_vector(_lrsOutput_, _dat_->n); 678 679 if (_dat_->nredundcol > 0) lrs_clear_mp_matrix(_Lin_, _dat_->nredundcol, _dat_->n); 680 681 if (_dat_->runs > 0) { 682 free(_dat_->isave); 683 free(_dat_->jsave); 684 } 685 686 auto savem = _dic_->m; /* need this to clear _dat_*/ 687 688 lrs_free_dic(_dic_, _dat_); /* deallocate lrs_dic */ 689 690 _dat_->m = savem; 691 lrs_free_dat(_dat_); 692 693 std::string name = "LrsWrapper:"; 694 std::vector< char > chars(name.c_str(), name.c_str() + name.size() + 1u); 695 696 lrs_close(&chars[0]); 697 698 // _coutOn_(); 699 } 700 701 template < typename GUM_SCALAR > _coutOff_()702 void LRSWrapper< GUM_SCALAR >::_coutOff_() const { 703 fflush(stdout); 704 #ifdef _MSC_VER 705 freopen("NUL", "w", stdout); 706 #else // _MSC_VER 707 _oldCout_ = dup(1); 708 709 int new_cout = open("/dev/null", O_WRONLY); 710 dup2(new_cout, 1); 711 close(new_cout); 712 #endif // _MSC_VER 713 } 714 715 template < typename GUM_SCALAR > _coutOn_()716 void LRSWrapper< GUM_SCALAR >::_coutOn_() const { 717 fflush(stdout); 718 #ifdef _MSC_VER 719 freopen("CON", "w", stdout); 720 #else // _MSC_VER 721 dup2(_oldCout_, 1); 722 close(_oldCout_); 723 #endif // _MSC_VER 724 } 725 726 } // namespace credal 727 } // namespace gum 728