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 <agrum/CN/tools/varMod2BNsMap.h>
23 
24 namespace gum {
25   namespace credal {
26 
27     template < typename GUM_SCALAR >
VarMod2BNsMap()28     VarMod2BNsMap< GUM_SCALAR >::VarMod2BNsMap() {
29       cnet = nullptr;
30 
31       GUM_CONSTRUCTOR(VarMod2BNsMap);
32     }
33 
34     template < typename GUM_SCALAR >
VarMod2BNsMap(const CredalNet<GUM_SCALAR> & cn)35     VarMod2BNsMap< GUM_SCALAR >::VarMod2BNsMap(const CredalNet< GUM_SCALAR >& cn) {
36       setCNet(cn);
37 
38       GUM_CONSTRUCTOR(VarMod2BNsMap);
39     }
40 
41     template < typename GUM_SCALAR >
~VarMod2BNsMap()42     VarMod2BNsMap< GUM_SCALAR >::~VarMod2BNsMap() {
43       GUM_DESTRUCTOR(VarMod2BNsMap);
44     }
45 
46     template < typename GUM_SCALAR >
setCNet(const CredalNet<GUM_SCALAR> & cn)47     void VarMod2BNsMap< GUM_SCALAR >::setCNet(const CredalNet< GUM_SCALAR >& cn) {
48       auto* cpt    = &cn.credalNet_currentCpt();
49       auto  nNodes = cpt->size();
50       sampleDef_.resize(nNodes);
51 
52       for (NodeId node = 0; node < nNodes; node++) {
53         auto pConfs = (*cpt)[node].size();
54         sampleDef_[node].resize(pConfs);
55 
56         for (Size pconf = 0; pconf < pConfs; pconf++) {
57           Size          nVertices = Size((*cpt)[node][pconf].size());
58           unsigned long b, c;   // needed by superiorPow
59           superiorPow(static_cast< unsigned long >(nVertices), b, c);
60           Size nBits = Size(b);
61           sampleDef_[node][pconf].resize(nBits);
62         }
63       }
64 
65       cnet = &cn;
66     }
67 
68     template < typename GUM_SCALAR >
insert(const std::vector<bool> & bn,const std::vector<Size> & key)69     bool VarMod2BNsMap< GUM_SCALAR >::insert(const std::vector< bool >& bn,
70                                              const std::vector< Size >& key) {
71       currentHash_            = Size(vectHash_(bn));
72       std::list< Size >& nets = myVarHashs_.getWithDefault(key, std::list< Size >());   //[ key ];
73 
74       for (std::list< Size >::iterator it = nets.begin(); it != nets.end(); ++it) {
75         if (*it == currentHash_) return false;
76       }
77 
78       // add it
79       myHashNet_.set(currentHash_, bn);   //[currentHash_] = bn;
80       // insert net hash in our key net list
81       nets.push_back(currentHash_);
82       // insert out key in the hash key list
83       myHashVars_.getWithDefault(currentHash_,
84                                  std::list< varKey >()) /*[currentHash_]*/.push_back(key);
85       return true;
86     }
87 
88     template < typename GUM_SCALAR >
insert(const std::vector<Size> & key,const bool isBetter)89     bool VarMod2BNsMap< GUM_SCALAR >::insert(const std::vector< Size >& key, const bool isBetter) {
90       if (isBetter) {
91         // get all nets of this key (maybe entry does not exists)
92         std::list< Size >& old_nets
93            = myVarHashs_.getWithDefault(key, std::list< Size >());   //[ key ];
94 
95         // for each one
96         for (std::list< Size >::iterator it = old_nets.begin(); it != old_nets.end(); ++it) {
97           // get all keys associated to this net
98           std::list< varKey >& netKeys
99              = myHashVars_.getWithDefault(*it, std::list< varKey >());   //[ *it ];
100 
101           // if we are the sole user, delete the net entry
102           if (netKeys.size() == 1) {
103             myHashVars_.erase(*it);
104           }
105           // other keys use the net, delete our key from list
106           else {
107             for (std::list< varKey >::iterator it2 = netKeys.begin(); it2 != netKeys.end(); ++it2) {
108               if (*it2 == key) {
109                 netKeys.erase(it2);
110                 break;
111               }
112             }
113           }
114         }   // end of : for each old_net
115 
116         // clear all old_nets
117         old_nets.clear();
118         // insert new net with it's hash
119         myHashNet_.set(currentHash_,
120                        currentSample_);   //[currentHash_] = currentSample_;
121         // insert net hash in our key net list
122         old_nets.push_back(currentHash_);
123         // insert out key in the hash key list
124         myHashVars_
125            .getWithDefault(currentHash_, std::list< varKey >()) /*[currentHash_]*/
126            .push_back(key);
127         return true;
128 
129       }   // end of isBetter
130       // another opt net
131       else {
132         // check that we didn't add it for this key
133         std::list< Size >& nets = myVarHashs_.getWithDefault(key, std::list< Size >());   //[ key ];
134 
135         for (std::list< Size >::iterator it = nets.begin(); it != nets.end(); ++it) {
136           if (*it == currentHash_) return false;
137         }
138 
139         // add it
140         myHashNet_.set(currentHash_, currentSample_);
141         // insert net hash in our key net list
142         nets.push_back(currentHash_);
143         // insert out key in the hash key list
144         myHashVars_.getWithDefault(currentHash_, std::list< varKey >()).push_back(key);
145 
146         /*
147               // add it
148               myHashNet_[currentHash_] = currentSample_;
149               // insert net hash in our key net list
150               nets.push_back(currentHash_);
151               // insert out key in the hash key list
152               myHashVars_[currentHash_].push_back(key);
153         */
154         return true;
155       }   // end of ! isBetter
156     }
157 
158     template < typename GUM_SCALAR >
setCurrentSample(const std::vector<std::vector<std::vector<bool>>> & sample)159     void VarMod2BNsMap< GUM_SCALAR >::setCurrentSample(
160        const std::vector< std::vector< std::vector< bool > > >& sample) {
161       currentSample_.clear();
162 
163       for (Size i = 0; i < sample.size(); i++)
164         for (Size j = 0; j < sample[j].size(); j++)
165           for (Size k = 0; k < sample[i][j].size(); k++)
166             currentSample_.push_back(sample[i][j][k]);
167 
168       // std::cout << sample << std::endl;
169       // std::cout << currentSample_ << std::endl;
170 
171       currentHash_ = Size(vectHash_(currentSample_));
172     }
173 
174     template < typename GUM_SCALAR >
getCurrentSample()175     const std::vector< bool >& VarMod2BNsMap< GUM_SCALAR >::getCurrentSample() {
176       return currentSample_;
177     }
178 
179     template < typename GUM_SCALAR >
180     const std::vector< std::vector< std::vector< bool > > >&
getSampleDef()181        VarMod2BNsMap< GUM_SCALAR >::getSampleDef() {
182       return sampleDef_;
183     }
184 
185     template < typename GUM_SCALAR >
186     const std::vector< std::vector< bool >* >
getBNOptsFromKey(const std::vector<Size> & key)187        VarMod2BNsMap< GUM_SCALAR >::getBNOptsFromKey(const std::vector< Size >& key) {
188       // return something even if key does not exist
189       if (!myVarHashs_.exists(key)) return std::vector< std::vector< bool >* >();
190 
191       std::list< Size >& netsHash = myVarHashs_[key];   //.at(key);
192 
193       std::vector< dBN* > nets;
194       nets.resize(netsHash.size());
195 
196       std::list< Size >::iterator it = netsHash.begin();
197 
198       for (Size i = 0; i < netsHash.size(); i++, ++it) {
199         nets[i] = &myHashNet_ /*.at(*/[*it];   //);
200       }
201 
202       return nets;
203     }
204 
205     template < typename GUM_SCALAR >
206     std::vector< std::vector< std::vector< std::vector< bool > > > >
getFullBNOptsFromKey(const std::vector<Size> & key)207        VarMod2BNsMap< GUM_SCALAR >::getFullBNOptsFromKey(const std::vector< Size >& key) {
208       if (cnet == nullptr)
209         GUM_ERROR(OperationNotAllowed,
210                   "No CredalNet associated to me ! Can't get FullBNOptsFromKey : " << key);
211 
212       if (!myVarHashs_.exists(key))
213         return std::vector< std::vector< std::vector< std::vector< bool > > > >();
214 
215       std::list< Size >& netsHash = myVarHashs_[key];   //.at(key);
216 
217       std::vector< std::vector< std::vector< std::vector< bool > > > > nets;
218       nets.resize(netsHash.size(), sampleDef_);
219 
220       std::list< Size >::iterator it = netsHash.begin();
221 
222       for (Size i = 0; i < netsHash.size(); i++, ++it) {
223         // std::vector< std::vector< std::vector < bool > > > net(sampleDef_);
224         dBN::iterator it2 = myHashNet_ /*.at(*/[*it] /*)*/.begin();
225 
226         for (Size j = 0; j < sampleDef_.size(); j++) {
227           for (Size k = 0; k < sampleDef_[j].size(); k++) {
228             for (Size l = 0; l < sampleDef_[j][k].size(); l++) {
229               nets[i][j][k][l] = *it2;
230               ++it2;
231             }
232           }
233         }
234       }
235 
236       return nets;
237     }
238 
239     template < typename GUM_SCALAR >
getEntrySize()240     Size VarMod2BNsMap< GUM_SCALAR >::getEntrySize() const {
241       return myHashNet_.size();
242     }
243 
244   }   // namespace credal
245 }   // namespace gum
246