AI 24/25 Project Software
Documentation for the AI 24/25 course programming project software
Loading...
Searching...
No Matches
open_list.h
1#ifndef OPEN_LIST_H
2#define OPEN_LIST_H
3
4#include <set>
5
6#include "downward/evaluation_context.h"
7#include "downward/operator_id.h"
8
9class StateID;
10
11template <class Entry>
12class OpenList {
13 bool only_preferred;
14
15protected:
16 /*
17 Insert an entry into the open list. This is called by insert, so
18 see comments there. This method will not be called if
19 is_terminal() is true or if only_preferred is true and the entry
20 to be inserted is not preferred. Hence, these conditions need
21 not be checked by the implementation.
22 */
23 virtual void
24 do_insertion(EvaluationContext& eval_context, const Entry& entry) = 0;
25
26public:
27 explicit OpenList(bool preferred_only = false);
28 virtual ~OpenList() = default;
29
30 /*
31 Insert an entry into the open list.
32
33 This method may be called with entries that the open list does
34 not want to insert, e.g. because they have an infinite estimate
35 or because they are non-preferred successor and the open list
36 only wants preferred successors. In this case, the open list
37 will remain unchanged.
38
39 This method will often compute heuristic estimates as a side
40 effect, which are cached in the EvaluationContext object that
41 is passed in.
42
43 Implementation note: uses the template method pattern, with
44 do_insertion performing the bulk of the work. See comments for
45 do_insertion.
46 */
47 void insert(EvaluationContext& eval_context, const Entry& entry);
48
49 /*
50 Remove and return the entry that should be expanded next.
51 */
52 virtual Entry remove_min() = 0;
53
54 // Return true if the open list is empty.
55 virtual bool empty() const = 0;
56
57 /*
58 Remove all elements from the open list.
59
60 TODO: This method might eventually go away, instead using a
61 mechanism for generating new open lists at a higher level.
62 This is currently only used by enforced hill-climbing.
63 */
64 virtual void clear() = 0;
65
66 /*
67 Called when the search algorithm wants to "boost" open lists
68 using preferred successors.
69
70 The default implementation does nothing. The main use case for
71 this is for alternation open lists.
72
73 TODO: Might want to change the name of the method to something
74 generic that reflects when it is called rather than how one
75 particular open list handles the event. I think this is called
76 on "search progress", so we should verify if this is indeed the
77 case, clarify what exactly that means, and then rename the
78 method to reflect this (e.g. with a name like
79 "on_search_progress").
80 */
81 virtual void boost_preferred();
82
83 /*
84 Add all path-dependent evaluators that this open lists uses (directly or
85 indirectly) into the result set.
86
87 TODO: This method can probably go away at some point.
88 */
89 virtual void get_path_dependent_evaluators(std::set<Evaluator*>& evals) = 0;
90
91 /*
92 Accessor method for only_preferred.
93
94 The only use case for this at the moment is for alternation open
95 lists, which boost those sublists which only include preferred
96 entries.
97
98 TODO: Is this sufficient reason to have this method? We could
99 get rid of it if instead AlternationOpenList would be passed
100 information upon construction which lists should be boosted on
101 progress. This could also make the code more general (it would
102 be easy to boost different lists by different amounts, and
103 boosting would not have to be tied to preferredness). We should
104 discuss the best way to proceed here.
105 */
106 bool only_contains_preferred_entries() const;
107
108 /*
109 is_terminal and is_reliable_dead_end return true if the state
110 associated with the passed-in evaluation context is deemed a
111 dead end by the open list.
112
113 The difference between the two methods is that
114 is_reliable_dead_end must guarantee that the associated state is
115 actually unsolvable, i.e., it must not believe the claims of
116 unsafe heuristics.
117
118 Like OpenList::insert, the methods usually evaluate heuristic
119 values, which are then cached in eval_context as a side effect.
120 */
121 virtual bool is_dead_end(EvaluationContext& eval_context) const = 0;
122 virtual bool
123 is_reliable_dead_end(EvaluationContext& eval_context) const = 0;
124};
125
126using StateOpenListEntry = StateID;
127using EdgeOpenListEntry = std::pair<StateID, OperatorID>;
128
129using StateOpenList = OpenList<StateOpenListEntry>;
130using EdgeOpenList = OpenList<EdgeOpenListEntry>;
131
132template <class Entry>
133OpenList<Entry>::OpenList(bool only_preferred)
134 : only_preferred(only_preferred)
135{
136}
137
138template <class Entry>
139void OpenList<Entry>::boost_preferred()
140{
141}
142
143template <class Entry>
144void OpenList<Entry>::insert(
145 EvaluationContext& eval_context,
146 const Entry& entry)
147{
148 if (only_preferred && !eval_context.is_preferred()) return;
149 if (!is_dead_end(eval_context)) do_insertion(eval_context, entry);
150}
151
152template <class Entry>
153bool OpenList<Entry>::only_contains_preferred_entries() const
154{
155 return only_preferred;
156}
157
158#endif