-
Notifications
You must be signed in to change notification settings - Fork 16
/
continuous_actions.hpp
633 lines (501 loc) · 24.6 KB
/
continuous_actions.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
/** @file continuous_actions.hpp
*
* Provides a default implementation for an action mapping that uses a set of continuous or hybrid actions,
* i.e. there is set of action categories, and the actions in each of these
* categories will map to the same child nodes in the belief tree.
*
* Continuous actions need to be constructed using action construction data which is a vector representation
* that is interpreted by the chooser.
*
* There is also support for additional discrete actions to be added to the set of actions.
*
* The mapping class stores the entries in an unordered_map indexed by the construction data for fast retrieval
*
*
* This involves subclasses of the following abstract classes:
* -ActionPool
* -ActionMapping
* -ActionMappingEntry
*
* as well as a serialization class providing methods to serialize this particular kind of
* action pool and action mapping.
*/
#ifndef SOLVER_CONTINUOUS_ACTIONS_HPP_
#define SOLVER_CONTINUOUS_ACTIONS_HPP_
#include <memory>
#include <vector>
#include "global.hpp"
#include "LinkedHashSet.hpp"
#include "solver/serialization/Serializer.hpp"
#include "solver/abstract-problem/Action.hpp"
#include "solver/abstract-problem/Model.hpp"
#include "solver/ActionNode.hpp"
#include "solver/mappings/actions/ActionPool.hpp"
#include "solver/mappings/actions/ActionMapping.hpp"
namespace solver {
class ContinuousActionMap;
class ContinuousActionMapEntry;
/** An abstract class that contains the data to construct continuous actions.
*
* The data has to be in vector form. The interface is storage and size agnostic.
* As such the constructiondata is only accessed though the data() function which
* returns a pointer to the array data of an std::array or std::vector or similar.
*
* The data() pointer only needs to point to the part relevant for the continuous
* action space. Additional discrete actions may be handled otherwise.
*
* Note, that a chooser for continuous actions is likely to make assumptions about
* the size of data(). It is expected that there is one value for each dimension.
*
*/
class ContinuousActionConstructionDataBase {
public:
virtual ~ContinuousActionConstructionDataBase() = default;
/** Returns a pointer to the data array of the underlying vector. If implemented using an std::array, just return std::array::data() */
virtual const double* data() const = 0;
};
/** An abstract class for continuous actions.
*
* An implementation should keep a copy of the construction data so a reference to it can
* be provided when needed.
*/
class ContinuousAction: public solver::Action {
public:
virtual const ContinuousActionConstructionDataBase& getConstructionData() const = 0;
};
/** An abstract service class for ContinuousActionMapp to store actions.
*
* Actions are stored in this container and indexed by the construction data.
*
* This is meant to be implemented as unodered_map.
*
* Implementations can tweak the hashing and equality functions used to create an
* equivalence relation for very similar actions.
*
*/
class ContinuousActionContainerBase {
public:
ContinuousActionContainerBase() = default;
virtual ~ContinuousActionContainerBase() = default;
_NO_COPY_OR_MOVE(ContinuousActionContainerBase);
/** like std::unordered_map::size() */
virtual size_t size() const = 0;
/** like std::unordered_map::at() */
virtual std::unique_ptr<ContinuousActionMapEntry>& at(const ContinuousActionConstructionDataBase& key) = 0;
/** like std::unordered_map::at() */
virtual const std::unique_ptr<ContinuousActionMapEntry>& at(const ContinuousActionConstructionDataBase& key) const = 0;
/** like std::unordered_map::operator[] */
virtual std::unique_ptr<ContinuousActionMapEntry>& operator[](const ContinuousActionConstructionDataBase& key) = 0;
/** like std::unordered_map::at() but only providing the data pointer for the construction data */
virtual std::unique_ptr<ContinuousActionMapEntry>& at(const double* constructionDataVector) = 0;
/** like std::unordered_map::at() but only providing the data pointer for the construction data */
virtual const std::unique_ptr<ContinuousActionMapEntry>& at(const double* constructionDataVector) const = 0;
/** like std::unordered_map::operator[] but only providing the data pointer for the construction data */
virtual std::unique_ptr<ContinuousActionMapEntry>& operator[](const double* constructionDataVector) = 0;
/** like std::unordered_map::clear() */
virtual void clear() = 0;
/** get all entries of the container */
virtual std::vector<ActionMappingEntry const*> getEntries() const = 0;
/** get all entries of the container with children.
*
* The default implementation uses getEntries() and then selects those with children.
* This works, but an implementation may choose to optimise the performance.
*/
virtual std::vector<ActionMappingEntry const*> getEntriesWithChildren() const;
/** get all entries of the container that are visited.
*
* The default implementation uses getEntries() and then selects those that are visited.
* This works, but an implementation may choose to optimise the performance.
*/
virtual std::vector<ActionMappingEntry const*> getEntriesWithNonzeroVisitCount() const;
};
/** An implementation of ContinuousActionContainerBase as template.
*
* It uses CONSTRUCTION_DATA::hash() and CONSTRUCTION_DATA::equal() to compare the keys.
*/
template<class CONSTRUCTION_DATA>
class ContinuousActionContainer: public ContinuousActionContainerBase {
public:
typedef CONSTRUCTION_DATA KeyType;
typedef typename KeyType::HashEqualOptions HashEqualOptions;
private:
/** Service class so the unordered_map can access hash() and equal(). */
class Comparator {
HashEqualOptions options;
public:
Comparator(const HashEqualOptions& theOptions): options(theOptions) {};
size_t operator()(const KeyType& key) const { return key.hash(options); }
size_t operator()(const KeyType& first, const KeyType& second) const { return first.equal(second, options); }
};
public:
ContinuousActionContainer(const HashEqualOptions& options): container(0, Comparator(options), Comparator(options)) {};
_NO_COPY_OR_MOVE(ContinuousActionContainer);
virtual size_t size() const override;
virtual std::unique_ptr<ContinuousActionMapEntry>& at(const ContinuousActionConstructionDataBase& key) override;
virtual const std::unique_ptr<ContinuousActionMapEntry>& at(const ContinuousActionConstructionDataBase& key) const override;
virtual std::unique_ptr<ContinuousActionMapEntry>& operator[](const ContinuousActionConstructionDataBase& key) override;
virtual std::unique_ptr<ContinuousActionMapEntry>& at(const double* constructionDataVector) override;
virtual const std::unique_ptr<ContinuousActionMapEntry>& at(const double* constructionDataVector) const override;
virtual std::unique_ptr<ContinuousActionMapEntry>& operator[](const double* constructionDataVector) override;
virtual void clear() override;
virtual std::vector<ActionMappingEntry const*> getEntries() const override;
virtual std::vector<ActionMappingEntry const*> getEntriesWithChildren() const override;
virtual std::vector<ActionMappingEntry const*> getEntriesWithNonzeroVisitCount() const override;
private:
std::unordered_map<CONSTRUCTION_DATA, std::unique_ptr<ContinuousActionMapEntry>, Comparator, Comparator> container = {};
};
/** An abstract implementation of the ActionPool interface that considers continuous actions
*
* A concrete implementation of this abstract class requires implementations for ...
*/
class ContinuousActionPool: public solver::ActionPool {
friend class ContinuousActionMap;
public:
typedef solver::Action Action;
typedef solver::BeliefNode BeliefNode;
typedef solver::ContinuousActionContainerBase ContinuousActionContainerBase;
typedef solver::ContinuousActionConstructionDataBase ContinuousActionConstructionDataBase;
public:
ContinuousActionPool() = default;
virtual ~ContinuousActionPool() = default;
_NO_COPY_OR_MOVE(ContinuousActionPool);
/** Returns a ContinuousActionMap for the given belief node. */
virtual std::unique_ptr<ActionMapping> createActionMapping(BeliefNode *node) override;
/** Returns a container to store actions within a ContinuousActionMap */
virtual std::unique_ptr<ContinuousActionContainerBase> createActionContainer(BeliefNode *node) const = 0;
/** Returns an action construction data object based on a vector of numbers that was provided.
*
* Here, constructionData is a pointer to a data array as it is returned by
* ContinuousActionConstructionDataBase::data(). It enables the action chooser to
* create new actions based on values it seems fit.
*/
virtual std::unique_ptr<ContinuousActionConstructionDataBase> createActionConstructionData(const double* constructionDataVector, const BeliefNode* belief) const = 0;
/** Returns an action based on the Construction Data that was provided.
*
* In this version, constructionData is a pointer to a data array as it is returned by
* ContinuousActionConstructionDataBase::data(). It enables the action chooser to
* create new actions based on values it seems fit.
*
* The default version uses createActionConstructionData first and then creates an action based
* on the full construction data. This might be inefficient and an implementation can override
* this function for a more direct approach.
*
* TODO: Check whether this function is actually used or can be removed.
*/
virtual std::unique_ptr<Action> createAction(const double* constructionDataVector, const BeliefNode* belief) const;
/** Returns an action based on the Construction Data that was provided.
*
* The default version calls createAction(constructionData.data()) which is probably fine
* in a purely continuous case, but probably not in a hybrid case.
*/
virtual std::unique_ptr<Action> createAction(const ContinuousActionConstructionDataBase& constructionData) const = 0;
/** Returns the initial bounding box for the continuous search.
*
* For each dimension, the first entry of the pair is the lower bound, the second entry is the upper bound.
*/
virtual std::vector<std::pair<double, double>> getInitialBoundingBox(BeliefNode* belief) const = 0;
/** Returns a shared pointer to a container containing the construction data for the additional fixed actions in a hybrid action space.
*
* The result is a shared pointer. Thus, the implementation can decide whether it wants to create the container and pass on ownership or it
* can return a reference to an internal vector without having to re-create it every time.
*
* The default version returns null to indicate there are no fixed actions.
*/
virtual std::vector<std::unique_ptr<ContinuousActionConstructionDataBase>> createFixedActions(const BeliefNode* belief) const;
/** This acts as a hint whether the chooser should try the fixed actions in the sequence they are given
* or randomise their order.
*
* It acts as a hint only and it depends on the chooser whether this option has any effect.
*
* The default version always returns true. (randomise actions)
*/
virtual bool randomiseFixedActions(const BeliefNode* belief) const;
};
/** The real base class for ChooserDataBase.
*
* Do not implement this, but ChooserDataBase instead so serialisation works.
*/
class ChooserDataBaseBase {
typedef ChooserDataBaseBase This;
typedef ContinuousActionMap ThisActionMap;
typedef ContinuousActionMapEntry ThisActionMapEntry;
public:
ChooserDataBaseBase() = default;
virtual ~ChooserDataBaseBase() = default;
_NO_COPY_OR_MOVE(ChooserDataBaseBase);
/** This function can return a marker attached with an action.
*
* Implementing something useful is optional (the default returns an empty string.
* This can be used for debugging and/or profiling.
*/
virtual std::string getActionMarker(const ThisActionMapEntry* entry) const;
void saveToStream(std::ostream& os, const ThisActionMap& map) const;
static std::unique_ptr<This> loadFromStream(std::istream& is, ThisActionMap& map);
protected:
typedef std::function<std::unique_ptr<ChooserDataBaseBase>(std::istream&, ThisActionMap& map)> LoadFromStreamFunction;
static void registerDerivedType(const std::string& name, const LoadFromStreamFunction& loader);
virtual void saveToStream_real(std::ostream& os, const ThisActionMap& map) const = 0;
private:
static std::unordered_map<std::string, LoadFromStreamFunction>& getDerivedLoadersSingleton();
};
/** A base class to hold data for the chooser.
*
* An implementation of this data structure can be stored in a continuous action map.
* Its use it at the chooser's discresion.
*
* The action map will take care of serialisation and destruction.
*
* implementation are expected to be constructible from std::istream for de-serialisation.
*
*/
template<class Derived>
class ChooserDataBase: public ChooserDataBaseBase {
typedef ChooserDataBase This;
typedef ChooserDataBaseBase Base;
public:
ChooserDataBase() = default;
virtual ~ChooserDataBase() = default;
_NO_COPY_OR_MOVE(ChooserDataBase);
private:
/** This function registers "Derived" with the base class
*
* This is needed for de-serialisation. It is then possible to load chooser data from file
* regardless of its type by having the type name written to the file.
*/
static void registerType();
/** Only a dummy variable. It is used to run registerType() at program start. */
static bool initialisationDummy;
/** A useless function that only accesses initialisationDummy.
*
* If initialisationDummy is used nowhere, it isn't instantiated and registerType() doesn't run.
*/
virtual void accessInitialisationDummy();
};
/** A concrete class implementing ActionMapping for a continuous or hybrid action space.
*
* This class stores its mapping entries in an unordered_map for easy access. In addition
* it allows the chooser to store and access additional data.
*/
class ContinuousActionMap: public solver::ActionMapping {
private:
typedef ContinuousActionMap This;
typedef ContinuousActionMapEntry ThisActionMapEntry;
typedef ContinuousAction ThisAction;
typedef ContinuousActionConstructionDataBase ThisActionConstructionData;
public:
friend class ContinuousActionMapEntry;
friend class ContinuousActionTextSerializer;
/** Constructs a new DiscretizedActionMap, which will be owned by the given belief node,
* and be associated with the given DiscretizedActionpool.
*
*/
ContinuousActionMap(BeliefNode *owner, ContinuousActionPool *pool);
// Default destructor; copying and moving disallowed!
virtual ~ContinuousActionMap() = default;
_NO_COPY_OR_MOVE(ContinuousActionMap);
/* -------------- Retrieval internal infrastructure members ---------------- */
const ContinuousActionPool* getActionPool() const;
/* -------------- Creation and retrieval of nodes. ---------------- */
virtual ActionNode *getActionNode(Action const &action) const override;
virtual ActionNode *createActionNode(Action const &action) override;
virtual long getNChildren() const override;
// TODO: This is not const. double check the interface. I think this should be changed everywhere in tapir...
virtual void deleteChild(ActionMappingEntry const *entry) override;
/* -------------- Retrieval of mapping entries. ---------------- */
virtual std::vector<ActionMappingEntry const *> getChildEntries() const override;
virtual long getNumberOfVisitedEntries() const override;
virtual std::vector<ActionMappingEntry const *> getVisitedEntries() const override;
virtual ActionMappingEntry *getEntry(Action const &action) override;
virtual ActionMappingEntry const *getEntry(Action const &action) const override;
ThisActionMapEntry* getActionMapEntry(const double* constructionDataVector);
ThisActionMapEntry* createOrGetActionMapEntry(const double* constructionDataVector);
const std::vector<ThisActionMapEntry*>& getFixedEntries() const;
/* ----------------- Methods for unvisited actions ------------------- */
/** Returns the next action to be tried for this node, or nullptr if there are no more. */
virtual std::unique_ptr<Action> getNextActionToTry() override;
/* -------------- Retrieval of general statistics. ---------------- */
virtual long getTotalVisitCount() const override;
/* The chooserData
*
* This class does not do much with it. It is just there as a place for the chooser
* to store data. Thus it is simply a public member.
*
* This class only takes care of desctruction, serialisation and de-serialisation
* of the data stored here. Otherwise the chooserData is left alone.
*/
std::unique_ptr<ChooserDataBaseBase> chooserData = nullptr;
protected:
/** The pool associated with this mapping. */
ContinuousActionPool *pool;
/** The container to store the action map entries. */
std::unique_ptr<ContinuousActionContainerBase> entries;
/** The number of action node children that have been created. */
long nChildren = 0;
/** The number of entries with nonzero visit counts. */
long numberOfVisitedEntries = 0;
/** The total of the visit counts of all of the individual entries. */
long totalVisitCount = 0;
/** Stores references to the entries that are considered fixed */
std::vector<ThisActionMapEntry*> fixedEntries;
};
/** A concrete class implementing ActionMappingEntry for a discretized action space.
*
* Each entry stores its bin number and a reference back to its parent map, as well as a child node,
* visit count, total and mean Q-values, and a flag for whether or not the action is legal.
*/
class ContinuousActionMapEntry : public solver::ActionMappingEntry {
typedef ContinuousActionMapEntry This;
typedef ContinuousActionMap ThisActionMap;
typedef ContinuousActionConstructionDataBase ThisActionConstructionData;
friend class ContinuousActionTextSerializer;
public:
ContinuousActionMapEntry(ThisActionMap* map, std::unique_ptr<ThisActionConstructionData>&& constructionData, bool isLegal = false);
_NO_COPY_OR_MOVE(ContinuousActionMapEntry);
virtual ActionMapping *getMapping() const override;
virtual std::unique_ptr<Action> getAction() const override;
virtual ActionNode *getActionNode() const override;
virtual long getVisitCount() const override;
virtual double getTotalQValue() const override;
virtual double getMeanQValue() const override;
virtual bool isLegal() const override;
/** Returns the bin number associated with this entry. */
long getBinNumber() const;
virtual bool update(long deltaNVisits, double deltaTotalQ) override;
virtual void setLegal(bool legal) override;
void setChild(std::unique_ptr<ActionNode>&& child);
void deleteChild();
const ActionNode* getChild() const;
const ThisActionConstructionData& getConstructionData() const;
virtual std::string getMarker() const override;
protected:
/** The parent action mapping. */
ContinuousActionMap* const map = nullptr;
/** The construction data represented by this entry */
std::unique_ptr<ThisActionConstructionData> constructionData;
/** The child action node, if one exists. */
std::unique_ptr<ActionNode> childNode = nullptr;
/** The visit count for this edge. */
long visitCount_ = 0;
/** The total Q-value for this edge. */
double totalQValue_ = 0;
/** The mean Q-value for this edge => should be equal to totalQValue_ / visitCount_ */
double meanQValue_ = 0;
/** True iff this edge is legal. */
bool isLegal_ = false; // Entries are illegal by default.
};
/** A partial implementation of the Serializer interface which provides serialization methods for
* the above continuous action mapping classes.
*/
class ContinuousActionTextSerializer: virtual public solver::Serializer {
typedef ContinuousActionTextSerializer This;
protected:
typedef ContinuousActionMap ThisActionMap;
typedef ContinuousActionMapEntry ThisActionMapEntry;
typedef ContinuousActionConstructionDataBase ThisActionConstructionDataBase;
public:
ContinuousActionTextSerializer() = default;
virtual ~ContinuousActionTextSerializer() = default;
_NO_COPY_OR_MOVE(ContinuousActionTextSerializer);
virtual void saveActionPool(ActionPool const &actionPool, std::ostream &os) override;
virtual std::unique_ptr<ActionPool> loadActionPool(std::istream &is) override;
virtual void saveActionMapping(ActionMapping const &map, std::ostream &os) override;
virtual std::unique_ptr<ActionMapping> loadActionMapping(BeliefNode *node, std::istream &is) override;
/** Loads the data from the input stream into the given ThisActionMap. */
virtual void loadActionMapping(ThisActionMap &map, std::istream &is);
protected:
virtual void saveActionMapEntry(const ThisActionMapEntry& entry, std::ostream& os);
virtual std::unique_ptr<ThisActionMapEntry> loadActionMapEntry(ThisActionMap& map, std::istream& is);
/** Saves the construction data to the output stream */
virtual void saveConstructionData(const ThisActionConstructionDataBase*, std::ostream& os) = 0;
/** Loads the construction data from the input stream */
virtual std::unique_ptr<ThisActionConstructionDataBase> loadConstructionData(std::istream& is) = 0;
};
/* ------------------- Template Implementations ------------------- */
/* ------------------- ContinuousActionContainer ------------------- */
template<class CONSTRUCTION_DATA>
inline size_t ContinuousActionContainer<CONSTRUCTION_DATA>::size() const {
return container.size();
}
template<class CONSTRUCTION_DATA>
inline std::unique_ptr<ContinuousActionMapEntry>& ContinuousActionContainer<CONSTRUCTION_DATA>::at(const ContinuousActionConstructionDataBase& key) {
return container.at(static_cast<const KeyType&>(key));
}
template<class CONSTRUCTION_DATA>
inline const std::unique_ptr<ContinuousActionMapEntry>& ContinuousActionContainer<CONSTRUCTION_DATA>::at(const ContinuousActionConstructionDataBase& key) const {
return container.at(static_cast<const KeyType&>(key));
}
template<class CONSTRUCTION_DATA>
inline std::unique_ptr<ContinuousActionMapEntry>& ContinuousActionContainer<CONSTRUCTION_DATA>::operator[](const ContinuousActionConstructionDataBase& key) {
return container[static_cast<const KeyType&>(key)];
}
template<class CONSTRUCTION_DATA>
inline std::unique_ptr<ContinuousActionMapEntry>& ContinuousActionContainer<CONSTRUCTION_DATA>::at(const double* constructionDataVector) {
return container.at(static_cast<const KeyType&>(KeyType(constructionDataVector)));
}
template<class CONSTRUCTION_DATA>
inline const std::unique_ptr<ContinuousActionMapEntry>& ContinuousActionContainer<CONSTRUCTION_DATA>::at(const double* constructionDataVector) const {
return container.at(static_cast<const KeyType&>(KeyType(constructionDataVector)));
}
template<class CONSTRUCTION_DATA>
inline std::unique_ptr<ContinuousActionMapEntry>& ContinuousActionContainer<CONSTRUCTION_DATA>::operator[](const double* constructionDataVector) {
return container[static_cast<const KeyType&>(KeyType(constructionDataVector))];
}
template<class CONSTRUCTION_DATA>
inline void ContinuousActionContainer<CONSTRUCTION_DATA>::clear() {
container.clear();
}
template<class CONSTRUCTION_DATA>
inline std::vector<ActionMappingEntry const*> ContinuousActionContainer<CONSTRUCTION_DATA>::getEntries() const {
std::vector<ActionMappingEntry const *> result;
result.reserve(container.size());
for(auto& i : container) {
result.push_back(i.second.get());
}
return std::move(result);
}
template<class CONSTRUCTION_DATA>
inline std::vector<ActionMappingEntry const*> ContinuousActionContainer<CONSTRUCTION_DATA>::getEntriesWithChildren() const {
std::vector<ActionMappingEntry const *> result;
// let's assume most of them have children.
result.reserve(container.size());
for(auto& i : container) {
ContinuousActionMapEntry const &entry = *(i.second);
if (entry.getChild() != nullptr) {
result.push_back(&entry);
}
}
return std::move(result);
}
template<class CONSTRUCTION_DATA>
inline std::vector<ActionMappingEntry const*> ContinuousActionContainer<CONSTRUCTION_DATA>::getEntriesWithNonzeroVisitCount() const {
std::vector<ActionMappingEntry const *> result;
// let's assume most of them have been visited.
result.reserve(container.size());
for(auto& i : container) {
ContinuousActionMapEntry const &entry = *(i.second);
if (entry.getVisitCount() > 0) {
if (!entry.isLegal()) {
debug::show_message("WARNING: Illegal entry with nonzero visit count!");
}
result.push_back(&entry);
}
}
return std::move(result);
}
/* ------------------- ChooserDataBase ------------------- */
template<class Derived>
bool ChooserDataBase<Derived>::initialisationDummy = (ChooserDataBase<Derived>::registerType(), true);
template<class Derived>
inline void ChooserDataBase<Derived>::registerType() {
LoadFromStreamFunction loaderFunction = [](std::istream& is, ContinuousActionMap& map) {
return Derived::loadFromStream(is, map);
};
registerDerivedType(typeid(Derived).name(), loaderFunction);
}
template<class Derived>
void ChooserDataBase<Derived>::accessInitialisationDummy() {
// make sure initialisationDummy is accessed.
if (initialisationDummy) {}
}
} /* namespace solver */
#endif /* SOLVER_CONTINUOUS_ACTIONS_HPP_ */