FMT 1.2.0
Forest management tools for forest planning
Loading...
Searching...
No Matches
FMTOutputNodeCache.h
Go to the documentation of this file.
1/*
2Copyright (c) 2019 Gouvernement du Qu�bec
3
4SPDX-License-Identifier: LiLiQ-R-1.1
5License-Filename: LICENSES/EN/LiLiQ-R11unicode.txt
6*/
7
8#ifndef FMToutputnodecache_H
9#define FMToutputnodecache_H
10
11#include<map>
12#include<vector>
13#include <unordered_map>
14#include "FMTOutputNode.h"
15#include <boost/serialization/serialization.hpp>
16#include <boost/serialization/map.hpp>
17#include <boost/serialization/vector.hpp>
18#include "FMTTheme.h"
19#include "FMTAction.h"
20#include "FMTGraph.hpp"
21
22
23
24namespace Graph
25{
26 // DocString: FMTOutputNodeCache
32 template <class tvdescriptor,class titerator>
34 {
35
36 public:
37 // DocString: FMTOutputNodeCache()
42 // DocString: FMTOutputNodeCache(const FMTOutputNodeCache&)
48 // DocString: FMTOutputNodeCache::operator=
55 // DocString: ~FMTOutputNodeCache()
60 // DocString: FMTOutputNodeCache(const std::vector<tvdescriptor>&)
65 FMTOutputNodeCache(const std::vector<tvdescriptor>& initialnodes) :
66 m_inmemorynodes(initialnodes), m_beginit(nullptr), m_endit(nullptr), m_searchtree(), m_allocator(), m_reserve()
67 {
68 m_inmemorynodes.shrink_to_fit();
69 std::sort(m_inmemorynodes.begin(),m_inmemorynodes.end());
70 }
71 // DocString: FMTOutputNodeCache(const titerator&, const titerator&, std::allocator<tvdescriptor>&, const size_t&)
79 FMTOutputNodeCache(const titerator& first, const titerator& last,std::allocator<tvdescriptor>& p_allocator,const size_t& p_reserve) :
80 m_inmemorynodes(), m_beginit(&first), m_endit(&last), m_searchtree(),m_allocator(&p_allocator), m_reserve(p_reserve)
81 {
82 if (m_reserve>0)
83 {
84 std::vector<tvdescriptor>allocated(*m_allocator);
85 allocated.reserve(m_reserve);
86 for (titerator it = *m_beginit; it != *m_endit; ++it)
87 {
88 allocated.push_back(*it);
89 }
90 m_beginit = nullptr;
91 m_endit = nullptr;
92 std::sort(allocated.begin(), allocated.end());
93 allocated.shrink_to_fit();
94 m_inmemorynodes.swap(allocated);
95 }
96
97 }
98 // DocString: FMTOutputNodeCache::eraseNode
104 {
105 m_searchtree.erase(node.source);
106 }
107
108 // DocString: FMTOutputNodeCache::contains
114 bool contains(const Core::FMTOutputNode& node) const
115 {
116 return m_searchtree.find(node.source) != m_searchtree.end();
117 }
118
119 // DocString: FMTOutputNodeCache::removeLargest
124 unsigned long long removeLargest()
125 {
126 size_t largestsize = 0;
127 unsigned long long removedmemory = 0;
128 notecacheit largestiterator = m_searchtree.end();
129 for (typename std::map<Core::FMTOutputSource, std::vector<tvdescriptor>>::iterator mapit = m_searchtree.begin(); mapit != m_searchtree.end(); mapit++)
130 {
131 size_t sizeofvec = mapit->second.size();
132 if (sizeofvec > largestsize)
133 {
134 largestsize = mapit->second.size();
135 largestiterator = mapit;
136 }
137
138 }
139 if (largestiterator != m_searchtree.end())
140 {
141 removedmemory = largestsize * sizeof(tvdescriptor);
142 m_searchtree.erase(largestiterator);
143 }
144 return removedmemory;
145 }
146 // DocString: FMTOutputNodeCache::getVertices
155 const std::vector<tvdescriptor>& getVertices(const Core::FMTOutputNode& targetnode, const std::vector<Core::FMTAction>& actions,
156 const std::vector<Core::FMTTheme>&themes, bool& exactvecticies) const
157 {
158 return this->_getCleanDescriptors(targetnode, actions, themes, exactvecticies);
159 }
160 // DocString: FMTOutputNodeCache::setValidVertices
166 void setValidVertices(const Core::FMTOutputNode& targetnode,const std::vector<tvdescriptor>& vertices) const
167 {
168 m_searchtree[targetnode.source] = vertices;
169 m_searchtree[targetnode.source].shrink_to_fit();
170 }
171 // DocString: FMTOutputNodeCache::clear
175 void clear()
176 {
177 m_beginit = nullptr;
178 m_endit = nullptr;
179 m_inmemorynodes.clear();
180 m_searchtree.clear();
181 }
182 // DocString: FMTOutputNodeCache::rebase
188 void rebase(const titerator& beginofdevs, const titerator& endofdevs)
189 {
190 m_beginit = &beginofdevs;
191 m_endit = &endofdevs;
192 }
193 // DocString: FMTOutputNodeCache::insert
198 void insert(const FMTOutputNodeCache& rhs)
199 {
200 if (m_beginit==nullptr)
201 {
202 if (m_inmemorynodes.size() < rhs.m_inmemorynodes.size())
203 {
204 m_inmemorynodes = rhs.m_inmemorynodes;
205 }
206 }
207
208 m_searchtree.insert(rhs.m_searchtree.begin(), rhs.m_searchtree.end());
209 }
210
211 // DocString: FMTOutputNodeCache::_pushToVector
216 void _pushToVector(std::vector<tvdescriptor>& refvecs) const
217 {
218 if (m_beginit!=nullptr)
219 {
220 for (titerator it = *m_beginit; it != *m_endit; ++it)
221 {
222 /*if (refvecs.capacity() <= (refvecs.size() + 1))
223 {
224 std::cout << "problem! "<< refvecs.capacity() <<"\n";
225 }*/
226 refvecs.push_back(*it);
227 }
228 refvecs.shrink_to_fit();
229 std::sort(refvecs.begin(), refvecs.end());
230 }
231 else {
232 refvecs = m_inmemorynodes;
233 }
234 }
235 private:
237 // DocString: FMTOutputNodeCache::serialize
244 template<class Archive>
245 void serialize(Archive& ar, const unsigned int version)
246 {
247 ar & boost::serialization::make_nvp("inmemorynodes", m_inmemorynodes);
248 ar & boost::serialization::make_nvp("searchtree", m_searchtree);
249 }
250 std::vector<tvdescriptor>m_inmemorynodes;
251 titerator const * m_beginit;
252 titerator const * m_endit;
253 mutable std::map<Core::FMTOutputSource,std::vector<tvdescriptor>>m_searchtree;
254 std::allocator<tvdescriptor>* m_allocator;
255 size_t m_reserve;
256 typedef typename std::map<Core::FMTOutputSource,std::vector<tvdescriptor>>::const_iterator notecacheit;
257
258 // DocString: FMTOutputNodeCache::_getCleanDescriptors
267 const std::vector<tvdescriptor>& _getCleanDescriptors(const Core::FMTOutputNode& targetnode,const std::vector<Core::FMTAction>& actions,
268 const std::vector<Core::FMTTheme>&themes, bool& exactnode) const
269 {
270 exactnode = false;
271 bool foundSubset = false;
272 typename std::map<Core::FMTOutputSource, std::vector<tvdescriptor>>::const_iterator parent = this->_getParentNode(targetnode,
273 actions, exactnode, foundSubset);
274 if (exactnode)
275 {
276 return parent->second;
277 }
278 //std::vector<tvdescriptor> cleaned(*m_allocator);
279 m_searchtree[targetnode.source] = std::vector<tvdescriptor>(*m_allocator);
280 std::vector<tvdescriptor>& cleaned = m_searchtree[targetnode.source];
281 if (foundSubset)
282 {
283 cleaned = parent->second;
284 }else {
285 cleaned.reserve(m_reserve);
286 _pushToVector(cleaned);
287 }
288 _getActionRebuild(targetnode, actions, cleaned, exactnode);// , TO_RESERVE); // should be able to find also exact!!!!!!!!
289 if (!exactnode)
290 {
291 std::vector<tvdescriptor>toRemove(*m_allocator);
292 bool gotSomething = false;
293 const Core::FMTMask& targetmask = targetnode.source.getMask();
294 for (typename std::map<Core::FMTOutputSource, std::vector<tvdescriptor>>::const_reverse_iterator sit = m_searchtree.rbegin();
295 sit != m_searchtree.rend(); sit++)
296 {
297 const Core::FMTMask& nodemask = sit->first.getMask();
298 if (targetmask.isNotThemesSubset(nodemask, themes))//deal only with mask
299 {
300 if (!gotSomething)
301 {
302 toRemove.reserve(cleaned.size());
303 }
304 toRemove.insert(toRemove.end(), sit->second.begin(), sit->second.end());
305 gotSomething = true;
306
307 }
308 }
309 if (!toRemove.empty())
310 {
311 std::vector<tvdescriptor>difference(*m_allocator);
312 difference.reserve(cleaned.size());
313 std::sort(toRemove.begin(), toRemove.end());
314 std::set_difference(cleaned.begin(), cleaned.end(),
315 toRemove.begin(), toRemove.end(), std::inserter(difference, difference.begin()));
316 cleaned.swap(difference);
317 }
318 }
319 //std::pair<notecacheit, bool> returniterator;
320 //returniterator = searchtree.insert(std::pair<Core::FMTOutputSource, std::vector<tvdescriptor>>(targetnode.source, cleaned));
321 //return (returniterator.first)->second;
322 return cleaned;
323 }
324 // DocString: FMTOutputNodeCache::_getActionRebuild
332 void _getActionRebuild(const Core::FMTOutputNode& targetnode,
333 const std::vector<Core::FMTAction>& actions,
334 std::vector<tvdescriptor>& cleaned,
335 bool& exactnode/*, const size_t& p_reserve*/) const
336 {
337 const std::string actionname = targetnode.source.getAction();
338 const std::vector<const Core::FMTAction*>aggregatesptr = Core::FMTActionComparator(actionname).getAllAggregates(actions, true);
339 if (!actionname.empty() && !aggregatesptr.empty()) //so it's a aggregate!
340 {
341 std::map<std::string, std::vector< notecacheit>>potentials;
342 for (const Core::FMTAction* attributeptr : aggregatesptr)
343 {
344 potentials[attributeptr->getName()] = std::vector< notecacheit>();
345 potentials[attributeptr->getName()].reserve(m_reserve);
346 }
347 for (notecacheit sit = m_searchtree.begin();
348 sit != m_searchtree.end(); sit++)
349 {
350 if (sit->first.isSubsetOf(targetnode.source, actions) &&
351 (sit->first != targetnode.source))
352 {
353 const std::string nodeaction = sit->first.getAction();
354 /*if (potentials[nodeaction].capacity() <= (potentials[nodeaction].size() + 1))
355 {
356 std::cout << "problem!/n";
357 }*/
358 potentials[nodeaction].push_back(sit);
359 }
360 }
361 for (const Core::FMTAction* attributeptr : aggregatesptr)
362 {
363 if (potentials.at(attributeptr->getName()).empty())
364 {
365 return; //not a perfect rebuilt need to be complete!!
366 }
367 }
368 typename std::vector< notecacheit>::const_iterator testting = potentials.begin()->second.begin();
369 while (testting != potentials.begin()->second.end())
370 {
371 size_t attid = 0;
372 std::vector<tvdescriptor>finalSelection((*testting)->second);
373 size_t insertingdone = 1;
374 for (const auto& attribute : potentials)
375 {
376 if (attid != 0)
377 {
378 for (notecacheit it : potentials.at(attribute.first))
379 {
380 if ((*testting)->first.isSameButDifferentAction(it->first))
381 {
382 finalSelection.insert(finalSelection.end(), it->second.begin(), it->second.end());
383 ++insertingdone;
384 break;
385 }
386
387 }
388
389 }
390 ++attid;
391 }
392 if (insertingdone == potentials.size())
393 {
394 std::sort(finalSelection.begin(), finalSelection.end());
395 //Weird fix BF
396 finalSelection.erase(std::unique(finalSelection.begin(), finalSelection.end()),finalSelection.end());
397 if ((*testting)->first.isSameButDifferentAction(targetnode.source)) //we got a exact match!!!
398 {
399 exactnode = true;
400 cleaned = finalSelection;
401 }
402 else {
403 std::vector<tvdescriptor>intersection;
404 std::set_intersection(cleaned.begin(), cleaned.end(),
405 finalSelection.begin(), finalSelection.end(), std::inserter(intersection, intersection.begin()));
406 cleaned = intersection;
407 }
408 }
409 ++testting;
410 }
411
412
413 }
414 }
415 // DocString: FMTOutputNodeCache::_getParentNode
424 notecacheit _getParentNode(const Core::FMTOutputNode& m_targetNode,
425 const std::vector<Core::FMTAction>& m_actions,
426 bool& m_exactNode, bool m_foundSubset) const
427 {
428 notecacheit parentit = m_searchtree.find(m_targetNode.source);
429 if (parentit != m_searchtree.end())
430 {
431 m_exactNode = true;
432 return parentit;
433 }
434 parentit = m_searchtree.begin();
435 m_exactNode = false;
436 m_foundSubset = false;
437 while (parentit != m_searchtree.end())
438 {
439 if (m_targetNode.source.isSubsetOf(parentit->first, m_actions))
440 {
441 m_foundSubset = true;
442 return parentit;
443 }
444 ++parentit;
445 }
446 return m_searchtree.end();
447 }
448 };
449
450
451
452}
453
454#endif
Comparator used to check if an action name (or aggregate) already exists in a std container.
Definition: FMTAction.h:421
std::vector< const FMTAction * > getAllAggregates(const std::vector< FMTAction > &actions, bool aggregateonly=false) const
Return the actions matching the action name, or only the matching aggregates.
List of specifications dictating the operability of a subset of developments to this action.
Definition: FMTAction.h:43
Core class holding, as a boost dynamic bitset, which theme attributes are part of a mask.
Definition: FMTMask.h:96
bool isNotThemesSubset(const FMTMask &rhs, const std::vector< const Core::FMTTheme * > &themes) const
Return true if this mask is not part of rhs based on the sorted themes.
void reserve(size_t p_size)
reserve memory for the boost dynamicbitset.
Node of an output representing a set of developments in the graph, holding a source,...
Definition: FMTOutputNode.h:25
FMTOutputSource source
Definition: FMTOutputNode.h:27
Source of an output holding a mask, a target and values, used to compute an output.
Definition: FMTOutputSource.h:44
const std::string & getAction() const
Return a const reference to the action of the output source.
Definition: FMTOutputSource.h:232
bool isSubsetOf(const FMTOutputSource &rhs, const std::vector< Core::FMTAction > &actions) const
Return true if this output source is a subset of another considering the actions.
const FMTMask & getMask() const
Return a const reference to the mask of the output source.
Definition: FMTOutputSource.h:186
Cache of graph vertices for output nodes, keyed by output source, used to speed up output computation...
Definition: FMTOutputNodeCache.h:34
FMTOutputNodeCache(const FMTOutputNodeCache &rhs)=default
Copy constructor for FMTOutputNodeCache.
const std::vector< tvdescriptor > & getVertices(const Core::FMTOutputNode &targetnode, const std::vector< Core::FMTAction > &actions, const std::vector< Core::FMTTheme > &themes, bool &exactvecticies) const
Return the vertices for a target node, using the cache.
Definition: FMTOutputNodeCache.h:155
FMTOutputNodeCache()=default
Default constructor for FMTOutputNodeCache.
void clear()
Clear the cache.
Definition: FMTOutputNodeCache.h:175
unsigned long long removeLargest()
Remove the largest entry of the cache and return the freed memory.
Definition: FMTOutputNodeCache.h:124
FMTOutputNodeCache & operator=(const FMTOutputNodeCache &rhs)=default
Copy assignment operator for FMTOutputNodeCache.
FMTOutputNodeCache(const titerator &first, const titerator &last, std::allocator< tvdescriptor > &p_allocator, const size_t &p_reserve)
Construct a cache from a range of nodes, an allocator and a reserve size.
Definition: FMTOutputNodeCache.h:79
void _pushToVector(std::vector< tvdescriptor > &refvecs) const
Push the nodes of the cache into a vector.
Definition: FMTOutputNodeCache.h:216
void eraseNode(const Core::FMTOutputNode &node)
Erase a node from the cache.
Definition: FMTOutputNodeCache.h:103
FMTOutputNodeCache(const std::vector< tvdescriptor > &initialnodes)
Construct a cache from an initial set of nodes.
Definition: FMTOutputNodeCache.h:65
friend class boost::serialization::access
Definition: FMTOutputNodeCache.h:236
void setValidVertices(const Core::FMTOutputNode &targetnode, const std::vector< tvdescriptor > &vertices) const
Set the valid vertices for a target node in the cache.
Definition: FMTOutputNodeCache.h:166
void insert(const FMTOutputNodeCache &rhs)
Insert the content of another cache into this cache.
Definition: FMTOutputNodeCache.h:198
~FMTOutputNodeCache()=default
Default destructor for FMTOutputNodeCache.
void rebase(const titerator &beginofdevs, const titerator &endofdevs)
Rebase the cache on a new range of developments.
Definition: FMTOutputNodeCache.h:188
bool contains(const Core::FMTOutputNode &node) const
Return true if the cache contains a node.
Definition: FMTOutputNodeCache.h:114
Definition: FMTAreaParser.h:35