Grail (C++)  1.4.0
A multi-platform, modular, universal engine for embedding advanced AI in games.
RouletteSelector.hh
1 // Copyright QED Software 2023.
2 
3 #ifndef GRAIL_ROULETTE_SELECTOR_H
4 #define GRAIL_ROULETTE_SELECTOR_H
5 
6 #include "RouletteOptions.hh"
7 #include "../Selectors/SelectionOption.hh"
8 #include "../Selectors/SelectionResult.hh"
9 #include "../../GrailEvaluators/Consideration.hh"
10 #include "../ConfigHelpers/DefaultRandomNumberGenerator.h"
11 
12 #include <algorithm>
13 #include <functional>
14 
15 namespace grail
16 {
17 namespace utility
18 {
22 namespace roulette_selector
23 {
24  template <typename ContextType>
34  void GetBestOption(const std::vector<SelectionOption<ContextType>>& options,
35  SelectionResult& result,
36  RandomNumberGenerator& randomNumberGenerator,
37  RouletteOptions rouletteOptions,
38  std::function<bool(const std::size_t&)> validator)
39  {
40  std::vector<std::pair<int, float>> legalIndexWeightPairs(options.size());
41  int bestRank = -1;
42  for (int i = 0; i < options.size(); ++i)
43  {
44  if (!validator(i))
45  {
46  continue;
47  }
48 
49  auto option = options[i];
50  int rank = option.rank;
51  evaluator::CacheConsiderationEvaluations(option.evaluator, option.context);
52  float weight = option.evaluator->EvaluateContext(option.context,
53  result.FetchNextEvaluatorSnapshot(option.evaluatedObjectName, option.evaluatedObjectMetadata, rank));
54 
55  if (rank >= bestRank)
56  {
57  if (weight < 0.0f)
58  {
59  continue;
60  }
61 
62  if (rank > bestRank)
63  {
64  legalIndexWeightPairs.clear();
65  bestRank = rank;
66  }
67 
68  legalIndexWeightPairs.emplace_back(i, weight);
69  }
70  }
71 
72  const int numberOfTopBehaviors = rouletteOptions.GetNumberOfTopBehaviors();
73  if (legalIndexWeightPairs.empty() || numberOfTopBehaviors == 0)
74  {
75  return;
76  }
77 
78  std::sort(legalIndexWeightPairs.begin(), legalIndexWeightPairs.end(), [](auto first, auto second) { return first.second > second.second; });
79 
80  size_t topOptionsLimit;
81  if(numberOfTopBehaviors > 0)
82  {
83  topOptionsLimit = std::min<size_t>(numberOfTopBehaviors, legalIndexWeightPairs.size());
84  }
85  else
86  {
87  topOptionsLimit = legalIndexWeightPairs.size();
88  }
89 
90  const float bestOptionWeight = legalIndexWeightPairs.front().second;
91  const float utilityThreshold = bestOptionWeight * rouletteOptions.GetRelativeUtilityThreshold();
92  float totalWeightOfBestRankOptions = bestOptionWeight;
93  for(int i = 1; i < topOptionsLimit; ++i)
94  {
95  const float optionUtility = legalIndexWeightPairs[i].second;
96  if(optionUtility < utilityThreshold)
97  {
98  break;
99  }
100 
101  totalWeightOfBestRankOptions += optionUtility;
102  }
103 
104  float thresholdValue = randomNumberGenerator.GetRandomPercentage() * totalWeightOfBestRankOptions;
105  for(const auto legalIndexWeightPair : legalIndexWeightPairs)
106  {
107  if (thresholdValue <= legalIndexWeightPair.second)
108  {
109  result.optionIndex = legalIndexWeightPair.first;
110  return;
111  }
112 
113  thresholdValue -= legalIndexWeightPair.second;
114  }
115  }
116 }
117 }
118 }
119 
120 #endif //GRAIL_ROULETTE_SELECTOR_H
grail::utility::SelectionResult::FetchNextEvaluatorSnapshot
data::UtilityEvaluatorSnapshot * FetchNextEvaluatorSnapshot(const std::string &evaluatedObjectName, const std::string &evaluatedObjectMetadata, int rank)
FetchNextEvaluatorSnapshot - If debugging mode was enabled in constructor, creates an empty snapshot ...
Definition: SelectionResult.hh:39
grail::utility::roulette_selector::RouletteOptions
RouletteSelectionOptions - Struct determining options for roulette selection.
Definition: RouletteOptions.hh:18
grail::utility::SelectionOption
The SelectionOption struct - Helper structure describing one of the options being selected by Selecto...
Definition: SelectionOption.hh:19
grail::utility::roulette_selector::GetBestOption
void GetBestOption(const std::vector< SelectionOption< ContextType >> &options, SelectionResult &result, RandomNumberGenerator &randomNumberGenerator, RouletteOptions rouletteOptions, std::function< bool(const std::size_t &)> validator)
GetBestOption - Selects most suitable option. Provides different context for each evaluated objects.
Definition: RouletteSelector.hh:34
grail::utility::SelectionResult::optionIndex
std::size_t optionIndex
optionIndex - Index of option selected by Selector.
Definition: SelectionResult.hh:67
grail::utility::SelectionResult
The SelectionResult struct - Structure containing results of operations done by Selector.
Definition: SelectionResult.hh:19
grail::utility::RandomNumberGenerator
Definition: RandomNumberGenerator.h:10