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 This file contains abstract class definitions influence diagrams 25 * inference classes. 26 * 27 * @author Pierre-Henri WUILLEMIN(_at_LIP6) and Christophe Gonzalez(@ 28 */ 29 #ifndef AGRUM_DECISIONPOTENTIAL_H 30 #define AGRUM_DECISIONPOTENTIAL_H 31 32 #include <agrum/tools/core/set.h> 33 #include <agrum/tools/variables/discreteVariable.h> 34 #include <agrum/tools/multidim/instantiation.h> 35 #include <agrum/tools/multidim/potential.h> 36 37 namespace gum { 38 /** 39 * @class DecisionPotential decisionPotential.h 40 *<agrum/ID/inference/decisionPotential.h> 41 * @brief Potential for optimization in LIMIDS (such as Single Policy Update) 42 */ 43 template < typename GUM_SCALAR > 44 class DecisionPotential { 45 public: 46 Potential< GUM_SCALAR > probPot; 47 Potential< GUM_SCALAR > utilPot; 48 DecisionPotential()49 explicit DecisionPotential() { 50 GUM_CONSTRUCTOR(DecisionPotential); 51 probPot.fillWith(GUM_SCALAR(1)); 52 utilPot.fillWith(GUM_SCALAR(0)); 53 } 54 ~DecisionPotential()55 ~DecisionPotential() { 56 GUM_DESTRUCTOR(DecisionPotential); 57 ; 58 } 59 DecisionPotential(const Potential<GUM_SCALAR> & prob,const Potential<GUM_SCALAR> & util)60 DecisionPotential(const Potential< GUM_SCALAR >& prob, const Potential< GUM_SCALAR >& util) : 61 probPot(prob), utilPot(util) { 62 GUM_CONSTRUCTOR(DecisionPotential); 63 } 64 DecisionPotential(const DecisionPotential<GUM_SCALAR> & dp)65 DecisionPotential(const DecisionPotential< GUM_SCALAR >& dp) : 66 probPot(dp.probPot), utilPot(dp.utilPot) { 67 GUM_CONS_CPY(DecisionPotential); 68 } 69 clear()70 void clear() { 71 gum::Potential< GUM_SCALAR > p; 72 p.fillWith(GUM_SCALAR(1)); 73 probPot = p; 74 p.fillWith(GUM_SCALAR(0)); 75 utilPot = p; 76 } 77 78 DecisionPotential< GUM_SCALAR >& operator=(const DecisionPotential< GUM_SCALAR >& src) { 79 GUM_OP_CPY(DecisionPotential); 80 if (&src == this) return *this; 81 probPot = src.probPot; 82 utilPot = src.utilPot; 83 return *this; 84 } 85 DecisionPotential(DecisionPotential<GUM_SCALAR> && dp)86 DecisionPotential(DecisionPotential< GUM_SCALAR >&& dp) : 87 probPot(std::forward< Potential< GUM_SCALAR > >(dp.probPot)), 88 utilPot(std::forward< Potential< GUM_SCALAR > >(dp.utilPot)) { 89 GUM_CONS_MOV(DecisionPotential); 90 } 91 92 DecisionPotential< GUM_SCALAR >& operator=(DecisionPotential< GUM_SCALAR >&& src) { 93 GUM_OP_MOV(DecisionPotential); 94 if (&src == this) return *this; 95 probPot = std::forward< Potential< GUM_SCALAR > >(src.probPot); 96 utilPot = std::forward< Potential< GUM_SCALAR > >(src.utilPot); 97 return *this; 98 } 99 100 bool operator==(const DecisionPotential< GUM_SCALAR >& p) const { 101 // @see Evaluating Influence Diagrams using LIMIDS (2000) - section 3.3 102 return ((p.probPot == this->probPot) 103 && (p.probPot * p.utilPot == this->probPot * this->utilPot)); 104 } 105 106 bool operator!=(const DecisionPotential< GUM_SCALAR >& p) const { return !operator==(p); } 107 variable(const std::string & name)108 const DiscreteVariable* variable(const std::string& name) const { 109 for (const auto& v: probPot.variablesSequence()) { 110 if (v->name() == name) return v; 111 } 112 for (const auto& v: utilPot.variablesSequence()) { 113 if (v->name() == name) return v; 114 } 115 116 GUM_ERROR(NotFound, "'" << name << "' can not be found in DecisionPotential.") 117 } 118 insertProba(const gum::Potential<GUM_SCALAR> & proba)119 void insertProba(const gum::Potential< GUM_SCALAR >& proba) { probPot *= proba; } 120 insertUtility(const gum::Potential<GUM_SCALAR> & util)121 void insertUtility(const gum::Potential< GUM_SCALAR >& util) { utilPot += util; } 122 123 DecisionPotential< GUM_SCALAR > operator*(const DecisionPotential< GUM_SCALAR >& dp1) const { 124 return DecisionPotential< GUM_SCALAR >::combination(*this, dp1); 125 } 126 127 DecisionPotential< GUM_SCALAR > operator*=(const DecisionPotential< GUM_SCALAR >& dp1) { 128 *this = DecisionPotential< GUM_SCALAR >::combination(*this, dp1); 129 return *this; 130 } 131 132 DecisionPotential< GUM_SCALAR > operator^(const Set< const DiscreteVariable* >& onto) const { 133 return DecisionPotential< GUM_SCALAR >::marginalization(*this, onto); 134 } 135 136 DecisionPotential< GUM_SCALAR > operator^(const std::vector< std::string >& ontonames) const { 137 return DecisionPotential< GUM_SCALAR >::marginalization(*this, ontonames); 138 } 139 140 divideEvenZero(const Potential<GUM_SCALAR> & p1,const Potential<GUM_SCALAR> & p2)141 static Potential< GUM_SCALAR > divideEvenZero(const Potential< GUM_SCALAR >& p1, 142 const Potential< GUM_SCALAR >& p2) { 143 Potential< GUM_SCALAR > res(p1); 144 Instantiation I(res); 145 for (I.setFirst(); !I.end(); I.inc()) { 146 if (res[I] != 0) res.set(I, res[I] / p2[I]); 147 } 148 return res; 149 } 150 combination(const DecisionPotential<GUM_SCALAR> & dp1,const DecisionPotential<GUM_SCALAR> & dp2)151 static DecisionPotential< GUM_SCALAR > combination(const DecisionPotential< GUM_SCALAR >& dp1, 152 const DecisionPotential< GUM_SCALAR >& dp2) { 153 return DecisionPotential< GUM_SCALAR >(dp1.probPot * dp2.probPot, dp1.utilPot + dp2.utilPot); 154 } 155 156 static DecisionPotential< GUM_SCALAR > marginalization(const DecisionPotential<GUM_SCALAR> & dp,const Set<const DiscreteVariable * > & onto)157 marginalization(const DecisionPotential< GUM_SCALAR >& dp, 158 const Set< const DiscreteVariable* >& onto) { 159 const auto pr = dp.probPot.margSumIn(onto); 160 return DecisionPotential(pr, divideEvenZero((dp.probPot * dp.utilPot).margSumIn(onto), pr)); 161 } 162 163 static DecisionPotential< GUM_SCALAR > marginalization(const DecisionPotential<GUM_SCALAR> & dp,const std::vector<std::string> & ontonames)164 marginalization(const DecisionPotential< GUM_SCALAR >& dp, 165 const std::vector< std::string >& ontonames) { 166 Set< const DiscreteVariable* > onto; 167 for (const auto& varname: ontonames) { 168 onto.insert(dp.variable(varname)); 169 } 170 return marginalization(dp, onto); 171 } 172 meanVar()173 std::pair< GUM_SCALAR, GUM_SCALAR > meanVar() { 174 auto tmp = probPot * utilPot; 175 GUM_SCALAR s = probPot.sum(); 176 double m = tmp.sum() / s; 177 double m2 = (tmp * utilPot).sum() / s; 178 return std::pair< GUM_SCALAR, GUM_SCALAR >(m, m2 - m * m); 179 } 180 toString()181 virtual std::string toString() const { 182 return "prob : " + probPot.toString() + " util:" + utilPot.toString(); 183 } 184 }; 185 186 template < typename GUM_SCALAR > 187 std::ostream& operator<<(std::ostream& out, const DecisionPotential< GUM_SCALAR >& array) { 188 out << array.toString(); 189 return out; 190 } 191 } // namespace gum 192 193 #endif // AGRUM_DECISIONPOTENTIAL_H 194