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 Source implementation of InfluenceDiagramGenerator 24 * 25 * @author Pierre-Henri WUILLEMIN(_at_LIP6) and Jean-Christophe MAGNAN and Christophe 26 * GONZALES(_at_AMU) 27 * 28 */ 29 #include <agrum/ID/generator/influenceDiagramGenerator.h> 30 31 namespace gum { 32 33 // Default constructor. 34 // Use the SimpleCPTGenerator for generating the IDs CPT. 35 template < typename GUM_SCALAR > InfluenceDiagramGenerator()36 InfluenceDiagramGenerator< GUM_SCALAR >::InfluenceDiagramGenerator() { 37 GUM_CONSTRUCTOR(InfluenceDiagramGenerator); 38 _cptGenerator_ = new SimpleCPTGenerator< GUM_SCALAR >(); 39 _utGenerator_ = new SimpleUTGenerator(); 40 } 41 42 // Use this constructor if you want to use a different policy for generating 43 // CPT than the default one. 44 // The cptGenerator will be erased when the destructor is called. 45 // @param cptGenerator The policy used to generate CPT. 46 template < typename GUM_SCALAR > InfluenceDiagramGenerator(ICPTGenerator<GUM_SCALAR> * cptGenerator)47 InfluenceDiagramGenerator< GUM_SCALAR >::InfluenceDiagramGenerator( 48 ICPTGenerator< GUM_SCALAR >* cptGenerator) { 49 GUM_CONSTRUCTOR(InfluenceDiagramGenerator); 50 _cptGenerator_ = cptGenerator; 51 _utGenerator_ = new SimpleUTGenerator(); 52 } 53 54 // Use this constructor if you want to use a different policy for generating 55 // UT than the default one. 56 // The utGenerator will be erased when the destructor is called. 57 // @param utGenerator The policy used to generate UT. 58 template < typename GUM_SCALAR > InfluenceDiagramGenerator(UTGenerator * utGenerator)59 InfluenceDiagramGenerator< GUM_SCALAR >::InfluenceDiagramGenerator(UTGenerator* utGenerator) { 60 GUM_CONSTRUCTOR(InfluenceDiagramGenerator); 61 _cptGenerator_ = new SimpleCPTGenerator< GUM_SCALAR >(); 62 _utGenerator_ = utGenerator; 63 } 64 65 // Use this constructor if you want to use a different policy for generating 66 // both CPT & UT than the defaults ones. 67 // The cptGenerator and utGenerator will be erased when the destructor is 68 // called. 69 // @param cptGenerator The policy used to generate CPT. 70 // @param utGenerator The policy used to generate UT. 71 template < typename GUM_SCALAR > InfluenceDiagramGenerator(ICPTGenerator<GUM_SCALAR> * cptGenerator,UTGenerator * utGenerator)72 InfluenceDiagramGenerator< GUM_SCALAR >::InfluenceDiagramGenerator( 73 ICPTGenerator< GUM_SCALAR >* cptGenerator, 74 UTGenerator* utGenerator) { 75 GUM_CONSTRUCTOR(InfluenceDiagramGenerator); 76 _cptGenerator_ = cptGenerator; 77 _utGenerator_ = utGenerator; 78 } 79 80 // Destructor. 81 template < typename GUM_SCALAR > ~InfluenceDiagramGenerator()82 InfluenceDiagramGenerator< GUM_SCALAR >::~InfluenceDiagramGenerator() { 83 GUM_DESTRUCTOR(InfluenceDiagramGenerator); 84 delete _cptGenerator_; 85 delete _utGenerator_; 86 } 87 88 // Generates an influence diagram using floats. 89 // @param nbrNodes The number of nodes in the generated ID. 90 // @param arcdensity The probability of adding an arc between two nodes. 91 // @param chanceNodeDensity The proportion of chance node 92 // @param utilityNodeDensity The proportion of utility node 93 // @param max_modality Each DRV has from 2 to max_modality modalities 94 // @return A IDs randomly generated. 95 template < typename GUM_SCALAR > 96 InfluenceDiagram< GUM_SCALAR >* generateID(Size nbrNodes,GUM_SCALAR arcDensity,GUM_SCALAR chanceNodeDensity,GUM_SCALAR utilityNodeDensity,Size max_modality)97 InfluenceDiagramGenerator< GUM_SCALAR >::generateID(Size nbrNodes, 98 GUM_SCALAR arcDensity, 99 GUM_SCALAR chanceNodeDensity, 100 GUM_SCALAR utilityNodeDensity, 101 Size max_modality) { 102 InfluenceDiagram< GUM_SCALAR >* influenceDiagram = new InfluenceDiagram< GUM_SCALAR >(); 103 // First we add nodes 104 HashTable< Size, NodeId > map; 105 std::stringstream strBuff; 106 Size nb_mod; 107 108 for (Idx i = 0; i < nbrNodes; ++i) { 109 strBuff << i; 110 nb_mod = (max_modality == 2) ? 2 : 2 + rand() % (max_modality - 1); 111 112 GUM_SCALAR cnd = chanceNodeDensity * (GUM_SCALAR)RAND_MAX; 113 GUM_SCALAR und = utilityNodeDensity * (GUM_SCALAR)RAND_MAX; 114 115 GUM_SCALAR d = (GUM_SCALAR)rand(); 116 117 if (d < cnd) 118 map.insert(i, 119 influenceDiagram->addChanceNode(LabelizedVariable(strBuff.str(), "", nb_mod))); 120 else if (d < (cnd + und)) 121 map.insert(i, influenceDiagram->addUtilityNode(LabelizedVariable(strBuff.str(), "", 1))); 122 else 123 map.insert(i, 124 influenceDiagram->addDecisionNode(LabelizedVariable(strBuff.str(), "", nb_mod))); 125 126 strBuff.str(""); 127 } 128 129 // We add arcs 130 GUM_SCALAR p = arcDensity * (GUM_SCALAR)RAND_MAX; 131 132 for (Size i = 0; i < nbrNodes; ++i) 133 if (!influenceDiagram->isUtilityNode(map[i])) 134 for (Size j = i + 1; j < nbrNodes; ++j) 135 if (((GUM_SCALAR)rand()) < p) { influenceDiagram->addArc(map[i], map[j]); } 136 137 // And fill the CPTs and UTs 138 for (Size i = 0; i < nbrNodes; ++i) 139 if (influenceDiagram->isChanceNode(map[i])) 140 _cptGenerator_->generateCPT( 141 influenceDiagram->cpt(map[i]).pos(influenceDiagram->variable(map[i])), 142 influenceDiagram->cpt(map[i])); 143 else if (influenceDiagram->isUtilityNode(map[i])) 144 _utGenerator_->generateUT( 145 influenceDiagram->utility(map[i]).pos(influenceDiagram->variable(map[i])), 146 influenceDiagram->utility(map[i])); 147 148 _checkTemporalOrder_(influenceDiagram); 149 150 return influenceDiagram; 151 } 152 153 template < typename GUM_SCALAR > _checkTemporalOrder_(InfluenceDiagram<GUM_SCALAR> * infdiag)154 void InfluenceDiagramGenerator< GUM_SCALAR >::_checkTemporalOrder_( 155 InfluenceDiagram< GUM_SCALAR >* infdiag) { 156 if (!infdiag->decisionOrderExists()) { 157 Sequence< NodeId > order = infdiag->topologicalOrder(true); 158 159 auto orderIter = order.begin(); 160 161 while ((orderIter != order.end()) && (!infdiag->isDecisionNode(*orderIter))) 162 ++orderIter; 163 164 if (orderIter == order.end()) return; 165 166 NodeId parentDecision = (*orderIter); 167 168 ++orderIter; 169 170 for (; orderIter != order.end(); ++orderIter) 171 if (infdiag->isDecisionNode(*orderIter)) { 172 infdiag->addArc(parentDecision, (*orderIter)); 173 parentDecision = (*orderIter); 174 } 175 } 176 } 177 178 } /* namespace gum */ 179