AI 24/25 Project Software
Documentation for the AI 24/25 course programming project software
Loading...
Searching...
No Matches
pattern_collection_generator_hillclimbing.h
1#ifndef PDBS_PATTERN_COLLECTION_GENERATOR_HILLCLIMBING_H
2#define PDBS_PATTERN_COLLECTION_GENERATOR_HILLCLIMBING_H
3
4#include "downward/pdbs/pattern_generator.h"
5#include "downward/pdbs/types.h"
6
7#include "downward/task_proxy.h"
8
9#include <cstdlib>
10#include <memory>
11#include <set>
12#include <vector>
13
14namespace utils {
15class CountdownTimer;
16class RandomNumberGenerator;
17} // namespace utils
18
19namespace sampling {
20class RandomWalkSampler;
21}
22
23namespace pdbs {
24class IncrementalCanonicalPDBs;
25class PatternDatabase;
26
27// Implementation of the pattern generation algorithm by Haslum et al.
28class PatternCollectionGeneratorHillclimbing
29 : public PatternCollectionGenerator {
30 // maximum number of states for each pdb
31 const int pdb_max_size;
32 // maximum added size of all pdbs
33 const int collection_max_size;
34 const int num_samples;
35 // minimal improvement required for hill climbing to continue search
36 const int min_improvement;
37 const double max_time;
38 std::shared_ptr<utils::RandomNumberGenerator> rng;
39
40 std::unique_ptr<IncrementalCanonicalPDBs> current_pdbs;
41
42 // for stats only
43 int num_rejected;
44 utils::CountdownTimer* hill_climbing_timer;
45
46 /*
47 For the given PDB, all possible extensions of its pattern by one
48 relevant variable are considered as candidate patterns. If the candidate
49 pattern has not been previously considered (not contained in
50 generated_patterns) and if building a PDB for it does not surpass the
51 size limit, then the PDB is built and added to candidate_pdbs.
52
53 The method returns the size of the largest PDB added to candidate_pdbs.
54 */
55 int generate_candidate_pdbs(
56 const TaskProxy& task_proxy,
57 const std::vector<std::vector<int>>& relevant_neighbours,
58 const PatternDatabase& pdb,
59 std::set<Pattern>& generated_patterns,
60 PDBCollection& candidate_pdbs);
61
62 /*
63 Performs num_samples random walks with a length (different for each
64 random walk) chosen according to a binomial distribution with
65 n = 4 * solution depth estimate and p = 0.5, starting from the initial
66 state. In each step of a random walk, a random operator is taken and
67 applied to the current state. If a dead end is reached or no more
68 operators are applicable, the walk starts over again from the initial
69 state. At the end of each random walk, the last state visited is taken as
70 a sample state, thus totalling exactly num_samples of sample states.
71 */
72 void sample_states(
73 const sampling::RandomWalkSampler& sampler,
74 int init_h,
75 std::vector<State>& samples);
76
77 /*
78 Searches for the best improving pdb in candidate_pdbs according to the
79 counting approximation and the given samples. Returns the improvement and
80 the index of the best pdb in candidate_pdbs.
81 */
82 std::pair<int, int> find_best_improving_pdb(
83 const std::vector<State>& samples,
84 const std::vector<int>& samples_h_values,
85 PDBCollection& candidate_pdbs);
86
87 /*
88 Returns true iff the h-value of the new pattern (from pdb) plus the
89 h-value of all pattern cliques from the current pattern
90 collection heuristic if the new pattern was added to it is greater than
91 the h-value of the current pattern collection.
92 */
93 bool is_heuristic_improved(
94 const PatternDatabase& pdb,
95 const State& sample,
96 int h_collection,
97 const PDBCollection& pdbs,
98 const std::vector<PatternClique>& pattern_cliques);
99
100 /*
101 This is the core algorithm of this class. The initial PDB collection
102 consists of one PDB for each goal variable. For each PDB of this initial
103 collection, the set of candidate PDBs are added (see
104 generate_candidate_pdbs) to the set of initial candidate PDBs.
105
106 The main loop of the search computes a set of sample states (see
107 sample_states) and uses this set to evaluate the set of all candidate PDBs
108 (see find_best_improving_pdb, using the "counting approximation"). If the
109 improvement obtained through adding the best PDB to the current heuristic
110 is smaller than the minimal required improvement, the search is stopped.
111 Otherwise, the best PDB is added to the heuristic and the candidate PDBs
112 for this best PDB are computed (see generate_candidate_pdbs) and used for
113 the next iteration.
114
115 This method uses a set to store all patterns that are generated as
116 candidate patterns in their "normal form" for duplicate detection.
117 Futhermore, a vector stores the PDBs corresponding to the candidate
118 patterns if its size does not surpass the user-specified size limit.
119 Storing the PDBs has the only purpose to avoid re-computation of the same
120 PDBs. This is quite a large time gain, but may use a lot of memory.
121 */
122 void hill_climbing(const TaskProxy& task_proxy);
123
124 virtual std::string name() const override;
125
126 /*
127 Runs the hill climbing algorithm. Note that the
128 initial pattern collection (consisting of exactly one PDB for each goal
129 variable) may break the maximum collection size limit, if the latter is
130 set too small or if there are many goal variables with a large domain.
131 */
132 virtual PatternCollectionInformation
133 compute_patterns(const std::shared_ptr<AbstractTask>& task) override;
134
135public:
136 PatternCollectionGeneratorHillclimbing(
137 int pdb_max_size,
138 int collection_max_size,
139 int num_samples,
140 int min_improvement,
141 double max_time,
142 int random_seed,
143 utils::Verbosity verbosity);
144
145 ~PatternCollectionGeneratorHillclimbing() override;
146};
147
148} // namespace pdbs
149
150#endif