AI 24/25 Project Software
Documentation for the AI 24/25 course programming project software
Loading...
Searching...
No Matches
pattern_database.h
1#ifndef PDBS_PATTERN_DATABASE_H
2#define PDBS_PATTERN_DATABASE_H
3
4#include "downward/pdbs/types.h"
5
6#include "downward/task_proxy.h"
7
8#include <utility>
9#include <vector>
10
11namespace utils {
12class LogProxy;
13class RandomNumberGenerator;
14} // namespace utils
15
16namespace pdbs {
17class AbstractOperator {
18 /*
19 This class represents an abstract operator how it is needed for
20 the regression search performed during the PDB-construction. As
21 all abstract states are represented as a number, abstract
22 operators don't have "usual" effects but "hash effects", i.e. the
23 change (as number) the abstract operator implies on a given
24 abstract state.
25 */
26 int concrete_op_id;
27
28 int cost;
29
30 /*
31 Preconditions for the regression search, corresponds to normal
32 effects and prevail of concrete operators.
33 */
34 std::vector<FactPair> regression_preconditions;
35
36 /*
37 Effect of the operator during regression search on a given
38 abstract state number.
39 */
40 int hash_effect;
41
42public:
43 /*
44 Abstract operators are built from concrete operators. The
45 parameters follow the usual name convention of SAS+ operators,
46 meaning prevail, preconditions and effects are all related to
47 progression search.
48 */
49 AbstractOperator(
50 const std::vector<FactPair>& prevail,
51 const std::vector<FactPair>& preconditions,
52 const std::vector<FactPair>& effects,
53 int cost,
54 const std::vector<int>& hash_multipliers,
55 int concrete_op_id);
56 ~AbstractOperator();
57
58 /*
59 Returns variable value pairs which represent the preconditions of
60 the abstract operator in a regression search
61 */
62 const std::vector<FactPair>& get_regression_preconditions() const
63 {
64 return regression_preconditions;
65 }
66
67 /*
68 Returns the effect of the abstract operator in form of a value
69 change (+ or -) to an abstract state index
70 */
71 int get_hash_effect() const { return hash_effect; }
72
73 int get_concrete_op_id() const { return concrete_op_id; }
74
75 /*
76 Returns the cost of the abstract operator (same as the cost of
77 the original concrete operator)
78 */
79 int get_cost() const { return cost; }
80 void dump(
81 const Pattern& pattern,
82 const VariablesProxy& variables,
83 utils::LogProxy& log) const;
84};
85
86// Implements a single pattern database
87class PatternDatabase {
88 Pattern pattern;
89
90 // size of the PDB
91 int num_states;
92
93 /*
94 final h-values for abstract-states.
95 dead-ends are represented by numeric_limits<int>::max()
96 */
97 std::vector<int> distances;
98
99 std::vector<int> generating_op_ids;
100 std::vector<std::vector<OperatorID>> wildcard_plan;
101
102 // multipliers for each variable for perfect hash function
103 std::vector<int> hash_multipliers;
104
105 /*
106 Recursive method; called by build_abstract_operators. In the case
107 of a precondition with value = -1 in the concrete operator, all
108 multiplied out abstract operators are computed, i.e. for all
109 possible values of the variable (with precondition = -1), one
110 abstract operator with a concrete value (!= -1) is computed.
111 */
112 void multiply_out(
113 int pos,
114 int cost,
115 std::vector<FactPair>& prev_pairs,
116 std::vector<FactPair>& pre_pairs,
117 std::vector<FactPair>& eff_pairs,
118 const std::vector<FactPair>& effects_without_pre,
119 const VariablesProxy& variables,
120 int concrete_op_id,
121 std::vector<AbstractOperator>& operators);
122
123 /*
124 Computes all abstract operators for a given concrete operator (by
125 its global operator number). Initializes data structures for initial
126 call to recursive method multiply_out. variable_to_index maps
127 variables in the task to their index in the pattern or -1.
128 */
129 void build_abstract_operators(
130 const OperatorProxy& op,
131 int cost,
132 const std::vector<int>& variable_to_index,
133 const VariablesProxy& variables,
134 std::vector<AbstractOperator>& operators);
135
136 /*
137 Computes all abstract operators, builds the match tree (successor
138 generator) and then does a Dijkstra regression search to compute
139 all final h-values (stored in distances). operator_costs can
140 specify individual operator costs for each operator for action
141 cost partitioning. If left empty, default operator costs are used.
142 */
143 void create_pdb(
144 const TaskProxy& task_proxy,
145 const std::vector<int>& operator_costs,
146 bool compute_plan,
147 const std::shared_ptr<utils::RandomNumberGenerator>& rng,
148 bool compute_wildcard_plan);
149
150 /*
151 For a given abstract state (given as index), the according values
152 for each variable in the state are computed and compared with the
153 given pairs of goal variables and values. Returns true iff the
154 state is a goal state.
155 */
156 bool is_goal_state(
157 int state_index,
158 const std::vector<FactPair>& abstract_goals,
159 const VariablesProxy& variables) const;
160
161 /*
162 The given concrete state is used to calculate the index of the
163 according abstract state. This is only used for table lookup
164 (distances) during search.
165 */
166 int hash_index(const std::vector<int>& state) const;
167
168public:
169 /*
170 Important: It is assumed that the pattern (passed via Options) is
171 sorted, contains no duplicates and is small enough so that the
172 number of abstract states is below numeric_limits<int>::max()
173 Parameters:
174 operator_costs: Can specify individual operator costs for each
175 operator. This is useful for action cost partitioning. If left
176 empty, default operator costs are used.
177 compute_plan: if true, compute an optimal plan when computing
178 distances of the PDB. This requires a RNG object passed via rng.
179 compute_wildcard_plan: when computing a plan (see compute_plan), compute
180 a wildcard plan, i.e., a sequence of parallel operators inducing an
181 optimal plan. Otherwise, compute a simple plan (a sequence of operators).
182 */
183 PatternDatabase(
184 const TaskProxy& task_proxy,
185 const Pattern& pattern,
186 const std::vector<int>& operator_costs = std::vector<int>(),
187 bool compute_plan = false,
188 const std::shared_ptr<utils::RandomNumberGenerator>& rng = nullptr,
189 bool compute_wildcard_plan = false);
190 ~PatternDatabase() = default;
191
192 int get_value(const std::vector<int>& state) const;
193 int get_value_for_index(std::size_t index) const;
194
195 // Returns the pattern (i.e. all variables used) of the PDB
196 const Pattern& get_pattern() const { return pattern; }
197
198 // Returns the size (number of abstract states) of the PDB
199 int get_size() const { return num_states; }
200
201 std::vector<std::vector<OperatorID>>&& extract_wildcard_plan()
202 {
203 return std::move(wildcard_plan);
204 };
205
206 /*
207 Returns the average h-value over all states, where dead-ends are
208 ignored (they neither increase the sum of all h-values nor the
209 number of entries for the mean value calculation). If all states
210 are dead-ends, infinity is returned.
211 Note: This is only calculated when called; avoid repeated calls to
212 this method!
213 */
214 double compute_mean_finite_h() const;
215
216 // Returns true iff op has an effect on a variable in the pattern.
217 bool is_operator_relevant(const OperatorProxy& op) const;
218};
219} // namespace pdbs
220
221#endif