HOG2
RangeCompression.cpp
Go to the documentation of this file.
1 #include "RangeCompression.h"
2 
3 #include <cassert>
4 #include <cstdint>
5 #include <iostream>
6 #include <limits>
7 #include <memory>
8 #include <vector>
9 
10 using namespace std;
11 
12 
14  int pos;
15  int h;
16  uint64_t numStates;
17 
18 public:
19  HeuristicTableEntry(int pos, int h, uint64_t numStates)
20  : pos(pos),
21  h(h),
22  numStates(numStates) {
23  }
24 
25  int GetPos() const {
26  return pos;
27  }
28 
29  int GetH() const {
30  return h;
31  }
32 
33  uint64_t GetNumStates() const {
34  return numStates;
35  }
36 
37  uint64_t GetPenalty(const HeuristicTableEntry &compressedEntry) const {
38  return (h - compressedEntry.h) * numStates;
39  }
40 };
41 
42 
44  /*
45  Represents the heuristic histogram in a more convenient form
46  than the vector<int> we get as an input.
47 
48  The representation excludes histogram entries with 0 states,
49  which is important for correctness. (The optimization algorithm
50  assumes that every admissible solution for a given subproblem
51  must include the lowest h value for that subproblem. This is
52  only true if there exists at least one entry with that h value.)
53  */
54 
55  vector<HeuristicTableEntry> entries;
56 
57 public:
58  explicit HeuristicTable(const vector<uint64_t> &histogram) {
59  for (size_t h = 0; h < histogram.size(); ++h) {
60  uint64_t numStates = histogram[h];
61  assert(numStates >= 0);
62  if (numStates) {
63  HeuristicTableEntry entry(entries.size(), h, numStates);
64  entries.push_back(entry);
65  }
66  }
67  }
68 
69  const HeuristicTableEntry &operator[](int pos) const {
70  return entries[pos];
71  }
72 
73  int GetSize() const {
74  return entries.size();
75  }
76 
77  uint64_t ComputeCostBetween(size_t startPos, size_t endPos) const {
78  const auto &compressedEntry = entries[startPos];
79  uint64_t cost = 0;
80  for (size_t pos = startPos; pos < endPos; ++pos)
81  cost += entries[pos].GetPenalty(compressedEntry);
82  return cost;
83  }
84 };
85 
86 
87 class Solution {
89  shared_ptr<const Solution> subsolution;
90  uint64_t cost;
91 
92  int GetFirstH() const {
93  return firstEntry->GetH();
94  }
95 
96  int GetNextH() const {
97  if (subsolution)
98  return subsolution->GetFirstH();
99  else
100  return numeric_limits<int>::max();
101  }
102 
103 public:
104  Solution(const HeuristicTable &hTable,
105  const HeuristicTableEntry &onlyEntry)
106  : firstEntry(&onlyEntry),
107  subsolution(nullptr),
108  cost(hTable.ComputeCostBetween(onlyEntry.GetPos(),
109  hTable.GetSize())) {
110  }
111 
112  Solution(const HeuristicTable &hTable,
113  const HeuristicTableEntry &firstEntry,
114  const shared_ptr<const Solution> &subsolution)
115  : firstEntry(&firstEntry),
116  subsolution(subsolution),
117  cost(hTable.ComputeCostBetween(firstEntry.GetPos(),
118  subsolution->firstEntry->GetPos()) +
119  subsolution->cost) {
120  }
121 
122  uint64_t GetCost() const {
123  return cost;
124  }
125 
126  vector<int> GetHValues() const {
127  vector<int> result;
128  const Solution *restSolution = this;
129  while (restSolution) {
130  result.push_back(restSolution->GetFirstH());
131  restSolution = restSolution->subsolution.get();
132  }
133  return result;
134  }
135 
136  double GetAverageH(const vector<uint64_t> &histogram) const {
137  // This method is only used for statistics in the test code.
138  double weightedH = 0.0;
139  double totalStates = 0.0;
140  const Solution *currentSolution = this;
141  for (size_t h = 0; h < histogram.size(); ++h) {
142  uint64_t numStates = histogram[h];
143  while (currentSolution->GetNextH() <= static_cast<int>(h))
144  currentSolution = currentSolution->subsolution.get();
145  weightedH += currentSolution->GetFirstH() * numStates;
146  totalStates += numStates;
147  }
148  return weightedH / totalStates;
149  }
150 };
151 
152 
153 static void DumpSolution(const Solution &solution,
154  const vector<uint64_t> &histogram) {
155  auto hValues = solution.GetHValues();
156  cout << "[";
157  for (size_t i = 0; i < hValues.size(); ++i) {
158  if (i != 0)
159  cout << ", ";
160  cout << hValues[i];
161  }
162  cout << "] with cost " << solution.GetCost()
163  << " and average h value " << solution.GetAverageH(histogram)
164  << endl;
165 }
166 
167 
168 static vector<int> Optimize(const vector<uint64_t> &histogram, int numValues,
169  bool dumpResult = false) {
170  assert(numValues >= 1);
171 
172  HeuristicTable hTable(histogram);
173 
174  vector<shared_ptr<const Solution>> subsolutions;
175  for (int iteration = 0; iteration < numValues; ++iteration) {
176  /*
177  Invariant: After k iterations, `subsolutions[pos]` contains
178  the best solution for the subproblem of compressing the
179  distribution that starts at position `pos` to at most k
180  values.
181  */
182  vector<shared_ptr<const Solution>> solutions;
183  solutions.reserve(hTable.GetSize());
184 
185  for (int pos = 0; pos < hTable.GetSize(); ++pos) {
186  const auto &entry = hTable[pos];
187  Solution bestSolution(hTable, entry);
188 
189  if (!subsolutions.empty()) {
190  for (int boundaryPos = pos + 1;
191  boundaryPos < hTable.GetSize();
192  ++boundaryPos) {
193  auto subsolution = subsolutions[boundaryPos];
194  Solution solution(hTable, entry, subsolution);
195  if (solution.GetCost() < bestSolution.GetCost())
196  bestSolution = solution;
197  }
198  }
199 
200  solutions.push_back(make_shared<Solution>(bestSolution));
201  }
202  subsolutions = move(solutions);
203  }
204 
205  auto solution = *subsolutions[0];
206 
207  if (dumpResult)
208  DumpSolution(solution, histogram);
209 
210  return solution.GetHValues();
211 }
212 
213 
214 void GetOptimizedBoundaries(const vector<uint64_t> &distribution,
215  int numValues, vector<int> &result) {
216  result = Optimize(distribution, numValues, false);
217 }
218 
219 
220 void DumpOptimizedBoundaries(const vector<uint64_t> &distribution, int numValues) {
221  Optimize(distribution, numValues, true);
222 }
HeuristicTableEntry::h
int h
Definition: RangeCompression.cpp:15
Solution::firstEntry
const HeuristicTableEntry * firstEntry
Definition: RangeCompression.cpp:88
RangeCompression.h
HeuristicTable
Definition: RangeCompression.cpp:43
HeuristicTableEntry::numStates
uint64_t numStates
Definition: RangeCompression.cpp:16
Solution::GetNextH
int GetNextH() const
Definition: RangeCompression.cpp:96
Solution::GetCost
uint64_t GetCost() const
Definition: RangeCompression.cpp:122
HeuristicTableEntry::GetPos
int GetPos() const
Definition: RangeCompression.cpp:25
HeuristicTableEntry::HeuristicTableEntry
HeuristicTableEntry(int pos, int h, uint64_t numStates)
Definition: RangeCompression.cpp:19
HeuristicTableEntry::GetH
int GetH() const
Definition: RangeCompression.cpp:29
Solution::GetFirstH
int GetFirstH() const
Definition: RangeCompression.cpp:92
Solution
Definition: RangeCompression.cpp:87
Solution::Solution
Solution(const HeuristicTable &hTable, const HeuristicTableEntry &onlyEntry)
Definition: RangeCompression.cpp:104
HeuristicTable::HeuristicTable
HeuristicTable(const vector< uint64_t > &histogram)
Definition: RangeCompression.cpp:58
HeuristicTableEntry::GetPenalty
uint64_t GetPenalty(const HeuristicTableEntry &compressedEntry) const
Definition: RangeCompression.cpp:37
HeuristicTableEntry::GetNumStates
uint64_t GetNumStates() const
Definition: RangeCompression.cpp:33
Solution::GetHValues
vector< int > GetHValues() const
Definition: RangeCompression.cpp:126
HeuristicTableEntry::pos
int pos
Definition: RangeCompression.cpp:14
max
#define max(a, b)
Definition: MinimalSectorAbstraction.cpp:40
GetOptimizedBoundaries
void GetOptimizedBoundaries(const vector< uint64_t > &distribution, int numValues, vector< int > &result)
Definition: RangeCompression.cpp:214
HeuristicTable::GetSize
int GetSize() const
Definition: RangeCompression.cpp:73
HeuristicTable::entries
vector< HeuristicTableEntry > entries
Definition: RangeCompression.cpp:55
DumpOptimizedBoundaries
void DumpOptimizedBoundaries(const vector< uint64_t > &distribution, int numValues)
Definition: RangeCompression.cpp:220
std
Definition: CanonicalGraphEnvironment.h:26
Optimize
static vector< int > Optimize(const vector< uint64_t > &histogram, int numValues, bool dumpResult=false)
Definition: RangeCompression.cpp:168
HeuristicTableEntry
Definition: RangeCompression.cpp:13
Solution::subsolution
shared_ptr< const Solution > subsolution
Definition: RangeCompression.cpp:89
HeuristicTable::ComputeCostBetween
uint64_t ComputeCostBetween(size_t startPos, size_t endPos) const
Definition: RangeCompression.cpp:77
Solution::cost
uint64_t cost
Definition: RangeCompression.cpp:90
DumpSolution
static void DumpSolution(const Solution &solution, const vector< uint64_t > &histogram)
Definition: RangeCompression.cpp:153
HeuristicTable::operator[]
const HeuristicTableEntry & operator[](int pos) const
Definition: RangeCompression.cpp:69
Solution::Solution
Solution(const HeuristicTable &hTable, const HeuristicTableEntry &firstEntry, const shared_ptr< const Solution > &subsolution)
Definition: RangeCompression.cpp:112
Solution::GetAverageH
double GetAverageH(const vector< uint64_t > &histogram) const
Definition: RangeCompression.cpp:136