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 /** @file 23 * @brief implementation of the base class for all elimination sequence 24 *algorithms 25 * 26 * @author Christophe GONZALES(_at_AMU) and Pierre-Henri WUILLEMIN(_at_LIP6) 27 */ 28 29 #include <agrum/agrum.h> 30 #include <agrum/tools/graphs/algorithms/triangulations/eliminationStrategies/eliminationSequenceStrategy.h> 31 32 #ifdef GUM_NO_INLINE 33 # include <agrum/tools/graphs/algorithms/triangulations/eliminationStrategies/eliminationSequenceStrategy_inl.h> 34 #endif // GUM_NOINLINE 35 36 namespace gum { 37 38 // an empty fill-ins set returned by default when we ask for a fill-ins set _empty_fill_ins_()39 const EdgeSet& EliminationSequenceStrategy::_empty_fill_ins_() { 40 #ifdef GUM_DEBUG_MODE 41 static bool first_use = true; 42 if (first_use) { 43 first_use = false; 44 __debug__::_dec_creation_("Set", " __empty_edge_set", 0, "static variable correction", 0); 45 __debug__::_dec_creation_("HashTable", 46 " __empty_edge_set", 47 0, 48 "static variable correction", 49 0); 50 } 51 #endif 52 static EdgeSet empty_fill_ins; 53 return empty_fill_ins; 54 } 55 56 // default constructor EliminationSequenceStrategy()57 EliminationSequenceStrategy::EliminationSequenceStrategy() { 58 GUM_CONSTRUCTOR(EliminationSequenceStrategy); 59 } 60 61 // constructor for an a priori non empty graph EliminationSequenceStrategy(UndiGraph * graph,const NodeProperty<Size> * domain_sizes)62 EliminationSequenceStrategy::EliminationSequenceStrategy( 63 UndiGraph* graph, 64 const NodeProperty< Size >* domain_sizes) { 65 EliminationSequenceStrategy::setGraph(graph, domain_sizes); 66 67 GUM_CONSTRUCTOR(EliminationSequenceStrategy); 68 } 69 70 // copy constructor EliminationSequenceStrategy(const EliminationSequenceStrategy & from)71 EliminationSequenceStrategy::EliminationSequenceStrategy( 72 const EliminationSequenceStrategy& from) : 73 graph_(from.graph_), 74 domain_sizes_(from.domain_sizes_), log_domain_sizes_(from.log_domain_sizes_) { 75 GUM_CONS_CPY(EliminationSequenceStrategy); 76 } 77 78 /// move constructor EliminationSequenceStrategy(EliminationSequenceStrategy && from)79 EliminationSequenceStrategy::EliminationSequenceStrategy(EliminationSequenceStrategy&& from) : 80 graph_(from.graph_), domain_sizes_(from.domain_sizes_), 81 log_domain_sizes_(std::move(from.log_domain_sizes_)) { 82 GUM_CONS_MOV(EliminationSequenceStrategy); 83 } 84 85 // destructor ~EliminationSequenceStrategy()86 EliminationSequenceStrategy::~EliminationSequenceStrategy() { 87 GUM_DESTRUCTOR(EliminationSequenceStrategy); 88 } 89 90 // performs all the graph/fill-ins updates provided eliminationUpdate(const NodeId node)91 void EliminationSequenceStrategy::eliminationUpdate(const NodeId node) {} 92 93 /** @brief in case fill-ins are provided, this function returns the fill-ins 94 * due to all the nodes eliminated so far */ fillIns()95 const EdgeSet& EliminationSequenceStrategy::fillIns() { return _empty_fill_ins_(); } 96 97 // clears the sequence (to prepare, for instance, a new elimination sequence) clear()98 void EliminationSequenceStrategy::clear() { 99 graph_ = nullptr; 100 domain_sizes_ = nullptr; 101 log_domain_sizes_.clear(); 102 } 103 104 // sets a new graph to be triangulated setGraph(UndiGraph * graph,const NodeProperty<Size> * dom_sizes)105 bool EliminationSequenceStrategy::setGraph(UndiGraph* graph, 106 const NodeProperty< Size >* dom_sizes) { 107 // check that both the graph and the domain sizes are different from nullptr 108 // or else that both are equal to nullptr 109 if (((graph != nullptr) && (dom_sizes == nullptr)) 110 || ((graph == nullptr) && (dom_sizes != nullptr))) { 111 GUM_ERROR(GraphError, 112 "EliminationSequenceStrategy: one of the graph or the set of " 113 "domain sizes is a null pointer."); 114 } 115 116 // check that each node has a domain size 117 if (graph != nullptr) { 118 for (const auto node: *graph) 119 if (!dom_sizes->exists(node)) 120 GUM_ERROR(GraphError, 121 "EliminationSequenceStrategy needs a domain size " 122 "for every node in the graph."); 123 } 124 125 // avoid empty modifications 126 if ((graph != graph_) || (dom_sizes != domain_sizes_)) { 127 // remove, if any, the current graph 128 clear(); 129 130 // assign a new graph 131 graph_ = graph; 132 domain_sizes_ = dom_sizes; 133 134 if (graph_ != nullptr) { 135 // compute the log of the modalities 136 log_domain_sizes_.resize(graph_->sizeNodes() / 2); 137 138 for (const auto node: *graph_) 139 log_domain_sizes_.insert(node, std::log((*domain_sizes_)[node])); 140 } 141 142 return true; 143 } 144 145 return false; 146 } 147 148 } /* namespace gum */ 149