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 /** 23 * @file 24 * @brief A Interface to all Causal Independence models 25 * 26 * Causal Independence (CI) is a method of defining a discrete distribution 27 * that can dramatically reduce the number of prior probabilities necessary to 28 * define a distribution. 29 * 30 * @author Pierre-Henri WUILLEMIN(_at_LIP6) & Christophe GONZALES(_at_AMU) 31 */ 32 #include <agrum/tools/core/bijection.h> 33 #include <agrum/tools/multidim/ICIModels/multiDimICIModel.h> 34 #include <agrum/tools/multidim/implementations/multiDimReadOnly.h> 35 36 namespace gum { 37 38 // Default constructor 39 template < typename GUM_SCALAR > MultiDimICIModel(GUM_SCALAR external_weight,GUM_SCALAR default_weight)40 INLINE MultiDimICIModel< GUM_SCALAR >::MultiDimICIModel(GUM_SCALAR external_weight, 41 GUM_SCALAR default_weight) : 42 MultiDimReadOnly< GUM_SCALAR >(), 43 _external_weight_(external_weight), _default_weight_(default_weight) { 44 GUM_CONSTRUCTOR(MultiDimICIModel); 45 } 46 47 // Default constructor 48 template < typename GUM_SCALAR > 49 INLINE MultiDimICIModel(const MultiDimICIModel<GUM_SCALAR> & from)50 MultiDimICIModel< GUM_SCALAR >::MultiDimICIModel(const MultiDimICIModel< GUM_SCALAR >& from) : 51 MultiDimReadOnly< GUM_SCALAR >(from) { 52 GUM_CONS_CPY(MultiDimICIModel); 53 _default_weight_ = from._default_weight_; 54 _external_weight_ = from._external_weight_; 55 _causal_weights_ = from._causal_weights_; 56 } 57 58 // Copy constructor using a bijection to replace variables from source. 59 template < typename GUM_SCALAR > MultiDimICIModel(const Bijection<const DiscreteVariable *,const DiscreteVariable * > & bij,const MultiDimICIModel<GUM_SCALAR> & from)60 INLINE MultiDimICIModel< GUM_SCALAR >::MultiDimICIModel( 61 const Bijection< const DiscreteVariable*, const DiscreteVariable* >& bij, 62 const MultiDimICIModel< GUM_SCALAR >& from) : 63 MultiDimReadOnly< GUM_SCALAR >() { 64 GUM_CONSTRUCTOR(MultiDimICIModel); 65 _default_weight_ = from._default_weight_; 66 _external_weight_ = from._external_weight_; 67 68 for (HashTableConstIteratorSafe< const DiscreteVariable*, GUM_SCALAR > iter 69 = from._causal_weights_.beginSafe(); 70 iter != from._causal_weights_.endSafe(); 71 ++iter) { 72 try { 73 causalWeight(*(bij.first(iter.key())), iter.val()); 74 } catch (NotFound&) { causalWeight(*(iter.key()), iter.val()); } 75 } 76 } 77 78 // destructor 79 template < typename GUM_SCALAR > ~MultiDimICIModel()80 INLINE MultiDimICIModel< GUM_SCALAR >::~MultiDimICIModel() { 81 GUM_DESTRUCTOR(MultiDimICIModel); 82 } 83 84 template < typename GUM_SCALAR > causalWeight(const DiscreteVariable & v)85 INLINE GUM_SCALAR MultiDimICIModel< GUM_SCALAR >::causalWeight(const DiscreteVariable& v) const { 86 return (_causal_weights_.exists(&v)) ? _causal_weights_[&v] : _default_weight_; 87 } 88 89 template < typename GUM_SCALAR > causalWeight(const DiscreteVariable & v,GUM_SCALAR w)90 INLINE void MultiDimICIModel< GUM_SCALAR >::causalWeight(const DiscreteVariable& v, 91 GUM_SCALAR w) const { 92 if (!this->contains(v)) { 93 GUM_ERROR(InvalidArgument, v.name() << " is not a cause for this CI Model") 94 } 95 96 if (w == (GUM_SCALAR)0) { GUM_ERROR(gum::OutOfBounds, "causal weight in CI Model>0") } 97 98 _causal_weights_.set(&v, w); 99 } 100 101 template < typename GUM_SCALAR > externalWeight()102 INLINE GUM_SCALAR MultiDimICIModel< GUM_SCALAR >::externalWeight() const { 103 return _external_weight_; 104 } 105 106 template < typename GUM_SCALAR > externalWeight(GUM_SCALAR w)107 INLINE void MultiDimICIModel< GUM_SCALAR >::externalWeight(GUM_SCALAR w) const { 108 _external_weight_ = w; 109 } 110 111 template < typename GUM_SCALAR > toString()112 std::string MultiDimICIModel< GUM_SCALAR >::toString() const { 113 std::stringstream s; 114 s << this->variable(0) << "=CIModel([" << externalWeight() << "],"; 115 116 for (Idx i = 1; i < this->nbrDim(); i++) { 117 s << this->variable(i) << "[" << causalWeight(this->variable(i)) << "]"; 118 } 119 120 s << ")"; 121 122 std::string res; 123 s >> res; 124 return res; 125 } 126 template < typename GUM_SCALAR > copyFrom(const MultiDimContainer<GUM_SCALAR> & src)127 void MultiDimICIModel< GUM_SCALAR >::copyFrom(const MultiDimContainer< GUM_SCALAR >& src) const { 128 auto p = dynamic_cast< const MultiDimICIModel< GUM_SCALAR >* >(&src); 129 if (p == nullptr) 130 MultiDimReadOnly< GUM_SCALAR >::copyFrom(src); 131 else { 132 if (src.domainSize() != this->domainSize()) { 133 GUM_ERROR(OperationNotAllowed, "Domain sizes do not fit") 134 } 135 _external_weight_ = p->_external_weight_; 136 _default_weight_ = p->_default_weight_; 137 for (Idx i = 1; i < this->nbrDim(); i++) { 138 _causal_weights_.set(const_cast< const DiscreteVariable* >(&this->variable(i)), 139 p->causalWeight(this->variable(i))); 140 } 141 } 142 } 143 144 // returns the name of the implementation 145 template < typename GUM_SCALAR > name()146 INLINE const std::string& MultiDimICIModel< GUM_SCALAR >::name() const { 147 static const std::string str = "MultiDimICIModel"; 148 return str; 149 } 150 151 template < typename GUM_SCALAR > replace_(const DiscreteVariable * x,const DiscreteVariable * y)152 INLINE void MultiDimICIModel< GUM_SCALAR >::replace_(const DiscreteVariable* x, 153 const DiscreteVariable* y) { 154 MultiDimReadOnly< GUM_SCALAR >::replace_(x, y); 155 _causal_weights_.insert(y, _causal_weights_[x]); 156 _causal_weights_.erase(x); 157 } 158 159 } /* namespace gum */ 160