(C++)  1.1.0
A multi-platform, modular, universal engine for embedding advanced AI in games.
EvaluatorHelpers.h
1 #ifndef GRAIL_EVALUATOR_HELPERS_H
2 #define GRAIL_EVALUATOR_HELPERS_H
3 
4 #include "../Curves/Curve.hh"
5 #include "../Aggregators/Aggregator.hh"
6 #include "../../GrailCore/Logger/LoggerManager.hh"
7 #include "../Aggregators/AverageAggregator.hh"
8 #include "../Aggregators/MaxAggregator.hh"
9 #include "../Aggregators/MinAggregator.hh"
10 #include "../Aggregators/ProductAggregator.hh"
11 #include "../Aggregators/SumAggregator.hh"
12 #include "../Curves/AllCurves.h"
13 #include "../../GrailData/UtilityModel/EvaluatorNodeModel.h"
14 #include "../../GrailData/UtilityModel/EvaluatorTreeModel.h"
15 #include "../../GrailData/UtilityModel/EvaluatorTreeReference.h"
16 #include "IConsiderationProvider.h"
17 
18 #include <algorithm>
19 #include <sstream>
20 
21 
22 namespace grail
23 {
24  namespace helpers
25  {
32  template<typename ContextType>
33  std::shared_ptr<utility::Aggregator<ContextType>> ConstructAggregator(const std::vector<std::shared_ptr<utility::Evaluator<ContextType>>>& inputEvaluators,
34  EvaluatorType evaluatorType)
35 
36  {
37  switch (evaluatorType)
38  {
39  case EvaluatorType::AGGREGATOR_MIN:
40  {
41  return std::make_shared<utility::MinAggregator<utility::EntityBlackboardPair>>(inputEvaluators);
42  }
43  case EvaluatorType::AGGREGATOR_MAX:
44  {
45  return std::make_shared<utility::MaxAggregator<utility::EntityBlackboardPair>>(inputEvaluators);
46  }
47  case EvaluatorType::AGGREGATOR_AVERAGE:
48  {
49  return std::make_shared<utility::AverageAggregator<utility::EntityBlackboardPair>>(inputEvaluators);
50  }
51  case EvaluatorType::AGGREGATOR_PRODUCT:
52  {
53  return std::make_shared<utility::ProductAggregator<utility::EntityBlackboardPair>>(inputEvaluators);
54  }
55  case EvaluatorType::AGGREGATOR_SUM:
56  {
57  return std::make_shared<utility::SumAggregator<utility::EntityBlackboardPair>>(inputEvaluators);
58  }
59  default:
60  {
61  GRAIL_LOG(consts::DEFAULT_GRAIL_LOG_GROUP, grail::Severity::ERRORS, "Invalid aggregator type");
62  return nullptr;
63  }
64  }
65  }
66 
74  template<typename ContextType>
75  std::shared_ptr<curves::Curve<ContextType>> ConstructCurve(const std::shared_ptr<utility::Evaluator<ContextType>>& inputEvaluator,
76  EvaluatorType evaluatorType, const std::vector<float>& curveParameters)
77  {
78  switch (evaluatorType)
79  {
80  case EvaluatorType::CURVE_LINEAR:
81  {
82  return std::make_shared<curves::LinearFunction<utility::EntityBlackboardPair>>(inputEvaluator, curveParameters[0],
83  curveParameters[1]);
84  }
85  case EvaluatorType::CURVE_POWER:
86  {
87  return std::make_shared<curves::PowerFunction<utility::EntityBlackboardPair>>(inputEvaluator, curveParameters[0],
88  curveParameters[1],
89  curveParameters[2]);
90  }
91  case EvaluatorType::CURVE_SIGMOID:
92  {
93  return std::make_shared<curves::SigmoidFunction<utility::EntityBlackboardPair>>(inputEvaluator, curveParameters[0],
94  curveParameters[1],
95  curveParameters[2],
96  curveParameters[3]);
97  }
98  case EvaluatorType::CURVE_UNIT_STEP:
99  {
100  return std::make_shared<curves::UnitStepFunction<utility::EntityBlackboardPair>>(inputEvaluator, curveParameters[0],
101  curveParameters[1],
102  curveParameters[2]);
103  }
104  case EvaluatorType::CURVE_EXPONENTIAL:
105  {
106  return std::make_shared<curves::ExponentialFunction<utility::EntityBlackboardPair>>(inputEvaluator, curveParameters[0]);
107  }
108  case EvaluatorType::CURVE_CONSTANT:
109  {
110  return std::make_shared<curves::ConstantFunction<utility::EntityBlackboardPair>>(inputEvaluator, curveParameters[0]);
111  }
112  case EvaluatorType::CURVE_LINEAR_INTERPOLATED:
113  {
114  std::vector<Vector2> points{};
115  for (size_t i = 0; i < curveParameters.size(); i += 2)
116  {
117  points.emplace_back(curveParameters[i], curveParameters[i + 1]);
118  }
119 
120  return std::make_shared<curves::LinearlyInterpolatedCurve<utility::EntityBlackboardPair>>(inputEvaluator, points);
121  }
122  case EvaluatorType::CURVE_BEZIER:
123  {
124  std::vector<Vector2> points{};
125  std::vector<Vector2> tangents{};
126 
127  for (size_t i = 0; i < curveParameters.size(); i += 4)
128  {
129  points.emplace_back(curveParameters[i], curveParameters[i + 1]);
130  tangents.emplace_back(curveParameters[i + 2], curveParameters[i + 3]);
131  }
132 
133  return std::make_shared<curves::BezierSpline<utility::EntityBlackboardPair>>(inputEvaluator, points, tangents);
134  }
135  case EvaluatorType::CURVE_STAIRCASE:
136  {
137  std::vector<grail::curves::StepData> stepData{};
138  for (size_t i = 0; i < curveParameters.size(); i += 2)
139  {
141  data.startPoint = curveParameters[i];
142  data.value = curveParameters[i + 1];
143  data.inclusiveStartPoint = true;
144  stepData.emplace_back(data);
145  }
146 
147  return std::make_shared<curves::StaircaseFunction<utility::EntityBlackboardPair>>(inputEvaluator, stepData);
148  }
149  case EvaluatorType::CURVE_LOWER_BOUND:
150  {
151  return std::make_shared<curves::LowerBound<utility::EntityBlackboardPair>>(inputEvaluator, curveParameters[0]);
152  }
153  case EvaluatorType::CURVE_UPPER_BOUND:
154  {
155  return std::make_shared<curves::UpperBound<utility::EntityBlackboardPair>>(inputEvaluator, curveParameters[0]);
156  }
157  case EvaluatorType::CURVE_DOUBLE_SIDED_BOUND:
158  {
159  return std::make_shared<curves::DoubleSidedBound<utility::EntityBlackboardPair>>(inputEvaluator, curveParameters[0], curveParameters[1]);
160  }
161  default:
162  {
163  GRAIL_LOG(consts::DEFAULT_GRAIL_LOG_GROUP, grail::Severity::ERRORS, "Invalid curve data type");
164  return nullptr;
165  }
166  }
167  }
168 
169 
170  namespace internal
171  {
172  enum class EvaluatorTypeGroup
173  {
174  CONSIDERATION,
175  CURVE,
176  AGGREGATOR,
177  SUBTREE_REFERENCE,
178  };
179 
180  EvaluatorTypeGroup GetEvaluatorTypeGroup(EvaluatorType evaluatorType);
181  EvaluatorNodeModel ResolveSubtreeDependencies(const EvaluatorNodeModel& inputModel,
182  const std::vector<EvaluatorTreeModel>& savedSubtrees);
183 
184  template<typename ContextType>
185  std::shared_ptr<utility::Evaluator<ContextType>> ConstructEvaluator(const EvaluatorNodeModel& resolvedModel,
186  const std::shared_ptr<const IConsiderationProvider<ContextType>>& considerationProvider)
187  {
188  EvaluatorTypeGroup evaluatorTypeGroup = GetEvaluatorTypeGroup(resolvedModel.evaluatorTypeId);
189  switch (evaluatorTypeGroup)
190  {
191  case EvaluatorTypeGroup::CONSIDERATION:
192  {
193  if (resolvedModel.inputEvaluatorModels.size() != 0)
194  {
195  std::stringstream ss;
196  ss << "Invalid config for consideration " << resolvedModel.considerationModel.name <<
197  ": considerations don't accept inputs";
198  GRAIL_LOG(consts::DEFAULT_GRAIL_LOG_GROUP, grail::Severity::ERRORS, ss.str());
199  return nullptr;
200  }
201  return considerationProvider->GetConsiderationByName(resolvedModel.considerationModel.name);
202  }
203  case EvaluatorTypeGroup::AGGREGATOR:
204  {
205  std::vector<std::shared_ptr<utility::Evaluator<utility::EntityBlackboardPair>>> inputEvaluators;
206  std::transform(resolvedModel.inputEvaluatorModels.begin(), resolvedModel.inputEvaluatorModels.end(),
207  std::back_inserter(inputEvaluators),
208  [&considerationProvider](const EvaluatorNodeModel& model)
209  {
210  return ConstructEvaluator(model, considerationProvider);
211  });
212  return ConstructAggregator(inputEvaluators, resolvedModel.evaluatorTypeId);
213  }
214  case EvaluatorTypeGroup::CURVE:
215  {
216  if (resolvedModel.inputEvaluatorModels.size() != 1)
217  {
218  std::stringstream ss;
219  ss << "Invalid config for utility curve: " << resolvedModel.inputEvaluatorModels.size() <<
220  " curve inputs provided, expected 1";
221  GRAIL_LOG(consts::DEFAULT_GRAIL_LOG_GROUP, grail::Severity::ERRORS, ss.str());
222  return nullptr;
223  }
224 
225  return ConstructCurve(ConstructEvaluator(resolvedModel.inputEvaluatorModels[0], considerationProvider),
226  resolvedModel.evaluatorTypeId, resolvedModel.curveDataModel.curveParameters);
227  }
228  default:
229  {
230  return nullptr;
231  }
232  }
233  }
234  }
235 
244  template<typename ContextType>
245  std::shared_ptr<utility::Evaluator<ContextType>> ConstructEvaluator(const EvaluatorNodeModel& inputModel,
246  const std::vector<EvaluatorTreeModel>& evaluatorTreeModels,
247  const std::shared_ptr<const IConsiderationProvider<ContextType>>& considerationProvider)
248  {
249  return internal::ConstructEvaluator(internal::ResolveSubtreeDependencies(inputModel, evaluatorTreeModels), considerationProvider);
250  }
251  }
252 }
253 
254 #endif //GRAIL_EVALUATOR_HELPERS_H
The StepData struct - Helper structure describing discrete values used in Staircase function.
Definition: StaircaseFunction.hh:14
float startPoint
startPoint - Start point of half-line extending to the right and having constant given value.
Definition: StaircaseFunction.hh:22
float value
value - Y-axis value.
Definition: StaircaseFunction.hh:18
bool inclusiveStartPoint
inclusiveStartPoint - Determines whether exact start point also has given value. If not,...
Definition: StaircaseFunction.hh:26