HOG2
PuzzleEntropy.h
Go to the documentation of this file.
1 //
2 // PuzzleEntropy.hpp
3 // The Witness Editor
4 //
5 // Created by Samarium on 2023-07-21.
6 // Copyright © 2023 MovingAI. All rights reserved.
7 //
8 #ifndef HOG2_GENERIC_PUZZLE_ENTROPY_H
9 #define HOG2_GENERIC_PUZZLE_ENTROPY_H
10 
11 #include <numeric>
12 #include <vector>
13 #include "PuzzleInferenceRule.h"
14 #include "SearchEnvironment.h"
15 #include "vectorCache.h"
16 
18 {
19  double value;
20  unsigned depth;
21 };
22 
23 template<class State, class Action>
24 class Entropy
25 {
26 protected:
27  static constexpr double inf = std::numeric_limits<double>::max();
31  bool isRelative = false;
32 
33  static void Softmin(const std::vector<double> &vars, std::vector<double> &ret)
34  {
35  double sum = std::accumulate(vars.begin(), vars.end(), 0.0, [](double r, double i) {
36  return r + std::exp(-i);
37  });
38  ret.reserve(vars.size());
39  std::transform(vars.begin(), vars.end(), std::back_inserter(ret), [&](double i) {
40  return std::exp(-i) / sum;
41  });
42  }
43 
44  static double KlDivergence(const std::vector<double> &p, const std::vector<double> &q)
45  {
46  if (p.size() != q.size())
47  throw std::invalid_argument("Input vectors must be of the same size.");
48  double divergence = 0.0;
49  for (size_t i = 0; i < p.size(); ++i)
50  {
51  if (p[i] != 0.0 && q[i] != 0.0)
52  divergence += p[i] * std::log2(p[i] / q[i]);
53  }
54  return divergence;
55  }
56 
57  double ImmediateEntropy(const std::vector<Action> &actions,
58  const std::vector<double> &childEntropy)
59  {
60  auto size = static_cast<double>(actions.size());
61  if (!isRelative)
62  return std::log2(size);
63  std::vector<double> &dist = *doubleCache.getItem();
64  Softmin(childEntropy, dist);
65  std::vector<double> &uniform = *doubleCache.getItem();
66  uniform.resize(actions.size());
67  std::generate(uniform.begin(), uniform.end(), [&]() { return 1 / size; });
68  auto kl = KlDivergence(dist, uniform);
69  doubleCache.returnItem(&dist);
70  doubleCache.returnItem(&uniform);
71  return kl;
72  }
73 
74 public:
76 
77  auto& SetRelative(bool val)
78  {
79  this->isRelative = val;
80  return *this;
81  }
82 
83  virtual EntropyInfo Calculate(const SearchEnvironment<State, Action> &env, State &state, unsigned lookahead)
84  {
85  if (env.GoalTest(state))
86  return { 0.0, 0 };
87  std::vector<Action> &allActions = *actCache.getItem();
88  env.GetActions(state, allActions);
89  ruleSet.FilterActions(env, state, allActions);
90  if (allActions.empty())
91  {
92  actCache.returnItem(&allActions);
93  return { inf, 0 };
94  }
95  std::vector<EntropyInfo> &childEntropyInfo = *entropyInfoCache.getItem();
96  for (auto &action: allActions)
97  {
98  env.ApplyAction(state, action);
99  childEntropyInfo.emplace_back(Calculate(env, state, (lookahead > 0) ? lookahead - 1 : 0));
100  env.UndoAction(state, action);
101  }
102  for (auto it = childEntropyInfo.begin(); it != childEntropyInfo.end(); )
103  {
104  auto &info = *it;
105  if (info.value == 0 && info.depth < lookahead)
106  return { 0.0, info.depth + 1 };
107  if (info.value == inf && info.depth < lookahead)
108  it = childEntropyInfo.erase(it);
109  else
110  ++it;
111  }
112  EntropyInfo entropyInfo;
113  if (std::all_of(childEntropyInfo.begin(), childEntropyInfo.end(), [](EntropyInfo &info) {
114  return info.value == 0;
115  }))
116  entropyInfo = { 0.0, childEntropyInfo[0].depth + 1 };
117  else if (std::all_of(childEntropyInfo.begin(), childEntropyInfo.end(), [](EntropyInfo &info) {
118  return info.value == inf;
119  }))
120  entropyInfo = { inf, childEntropyInfo[0].depth + 1 };
121  else
122  {
123  auto &min_childEntropyInfo = *std::min_element(childEntropyInfo.begin(), childEntropyInfo.end(),
124  [](EntropyInfo &info1, EntropyInfo &info2){
125  return info1.value < info2.value;
126  });
127  auto childEntropy = std::vector<double>();
128  childEntropy.reserve(childEntropyInfo.size());
129  std::transform(childEntropyInfo.begin(), childEntropyInfo.end(), std::back_inserter(childEntropy),
130  [](EntropyInfo &info){ return info.value; });
131  entropyInfo = { min_childEntropyInfo.value + ImmediateEntropy(allActions, childEntropy),
132  min_childEntropyInfo.depth + 1 };
133  }
134  actCache.returnItem(&allActions);
135  return entropyInfo;
136  }
137 };
138 
139 #endif /* HOG2_GENERIC_PUZZLE_ENTROPY_H */
Entropy::entropyInfoCache
vectorCache< EntropyInfo > entropyInfoCache
Definition: PuzzleEntropy.h:29
Entropy::Calculate
virtual EntropyInfo Calculate(const SearchEnvironment< State, Action > &env, State &state, unsigned lookahead)
Definition: PuzzleEntropy.h:83
EntropyInfo::depth
unsigned depth
Definition: PuzzleEntropy.h:20
Entropy::ImmediateEntropy
double ImmediateEntropy(const std::vector< Action > &actions, const std::vector< double > &childEntropy)
Definition: PuzzleEntropy.h:57
Entropy
Definition: PuzzleEntropy.h:24
SearchEnvironment::UndoAction
virtual void UndoAction(state &s, action a) const
Definition: SearchEnvironment.h:40
Entropy::KlDivergence
static double KlDivergence(const std::vector< double > &p, const std::vector< double > &q)
Definition: PuzzleEntropy.h:44
vectorCache.h
SearchEnvironment::GetActions
virtual void GetActions(const state &nodeID, std::vector< action > &actions) const =0
PuzzleInferenceRule.h
Entropy::doubleCache
vectorCache< double > doubleCache
Definition: PuzzleEntropy.h:30
vectorCache::returnItem
void returnItem(std::vector< storage > *)
Definition: vectorCache.h:62
Entropy::Softmin
static void Softmin(const std::vector< double > &vars, std::vector< double > &ret)
Definition: PuzzleEntropy.h:33
vectorCache::getItem
std::vector< storage > * getItem()
Definition: vectorCache.h:39
Entropy::actCache
vectorCache< Action > actCache
Definition: PuzzleEntropy.h:28
PuzzleInferenceRuleSet
Definition: PuzzleInferenceRule.h:25
Entropy::SetRelative
auto & SetRelative(bool val)
Definition: PuzzleEntropy.h:77
max
#define max(a, b)
Definition: MinimalSectorAbstraction.cpp:40
vectorCache< Action >
Entropy::isRelative
bool isRelative
Definition: PuzzleEntropy.h:31
EntropyInfo::value
double value
Definition: PuzzleEntropy.h:19
Entropy::inf
static constexpr double inf
Definition: PuzzleEntropy.h:27
Entropy::ruleSet
PuzzleInferenceRuleSet< State, Action > ruleSet
Definition: PuzzleEntropy.h:75
SearchEnvironment::ApplyAction
virtual void ApplyAction(state &s, action a) const =0
SearchEnvironment::GoalTest
virtual bool GoalTest(const state &node, const state &goal) const =0
SearchEnvironment
Definition: SearchEnvironment.h:30
SearchEnvironment.h
EntropyInfo
Definition: PuzzleEntropy.h:17