AI 24/25 Project Software
Documentation for the AI 24/25 course programming project software
Loading...
Searching...
No Matches
lm_cut_landmarks.h
1#ifndef HEURISTICS_LM_CUT_LANDMARKS_H
2#define HEURISTICS_LM_CUT_LANDMARKS_H
3
4#include "downward/task_proxy.h"
5
6#include "downward/algorithms/priority_queues.h"
7
8#include <cassert>
9#include <functional>
10#include <memory>
11#include <vector>
12
13namespace lm_cut_heuristic {
14// TODO: Fix duplication with the other relaxation heuristics.
15struct RelaxedProposition;
16
17enum PropositionStatus {
18 UNREACHED = 0,
19 REACHED = 1,
20 GOAL_ZONE = 2,
21 BEFORE_GOAL_ZONE = 3
22};
23
24struct RelaxedOperator {
25 int original_op_id;
26 std::vector<RelaxedProposition*> preconditions;
27 std::vector<RelaxedProposition*> effects;
28 int base_cost; // 0 for axioms, 1 for regular operators
29
30 int cost;
31 int unsatisfied_preconditions;
32 int h_max_supporter_cost; // h_max_cost of h_max_supporter
33 RelaxedProposition* h_max_supporter;
34 RelaxedOperator(
35 std::vector<RelaxedProposition*>&& pre,
36 std::vector<RelaxedProposition*>&& eff,
37 int op_id,
38 int base)
39 : original_op_id(op_id)
40 , preconditions(pre)
41 , effects(eff)
42 , base_cost(base)
43 {
44 }
45
46 inline void update_h_max_supporter();
47};
48
49struct RelaxedProposition {
50 std::vector<RelaxedOperator*> precondition_of;
51 std::vector<RelaxedOperator*> effect_of;
52
53 PropositionStatus status;
54 int h_max_cost;
55};
56
57class LandmarkCutLandmarks {
58 std::vector<RelaxedOperator> relaxed_operators;
59 std::vector<std::vector<RelaxedProposition>> propositions;
60 RelaxedProposition artificial_precondition;
61 RelaxedProposition artificial_goal;
62 int num_propositions;
63 priority_queues::AdaptiveQueue<RelaxedProposition*> priority_queue;
64
65 void build_relaxed_operator(const OperatorProxy& op);
66 void add_relaxed_operator(
67 std::vector<RelaxedProposition*>&& precondition,
68 std::vector<RelaxedProposition*>&& effects,
69 int op_id,
70 int base_cost);
71 RelaxedProposition* get_proposition(const FactProxy& fact);
72 void setup_exploration_queue();
73 void setup_exploration_queue_state(const State& state);
74 void first_exploration(const State& state);
75 void first_exploration_incremental(std::vector<RelaxedOperator*>& cut);
76 void second_exploration(
77 const State& state,
78 std::vector<RelaxedProposition*>& second_exploration_queue,
79 std::vector<RelaxedOperator*>& cut);
80
81 void enqueue_if_necessary(RelaxedProposition* prop, int cost)
82 {
83 assert(cost >= 0);
84 if (prop->status == UNREACHED || prop->h_max_cost > cost) {
85 prop->status = REACHED;
86 prop->h_max_cost = cost;
87 priority_queue.push(cost, prop);
88 }
89 }
90
91 void mark_goal_plateau(RelaxedProposition* subgoal);
92 void validate_h_max() const;
93
94public:
95 using Landmark = std::vector<int>;
96 using CostCallback = std::function<void(int)>;
97 using LandmarkCallback = std::function<void(const Landmark&, int)>;
98
99 LandmarkCutLandmarks(const TaskProxy& task_proxy);
100
101 /*
102 Compute LM-cut landmarks for the given state.
103
104 If cost_callback is not nullptr, it is called once with the cost of each
105 discovered landmark.
106
107 If landmark_callback is not nullptr, it is called with each discovered
108 landmark (as a vector of operator indices) and its cost. This requires
109 making a copy of the landmark, so cost_callback should be used if only the
110 cost of the landmark is needed.
111
112 Returns true iff state is detected as a dead end.
113 */
114 bool compute_landmarks(
115 const State& state,
116 const CostCallback& cost_callback,
117 const LandmarkCallback& landmark_callback);
118};
119
120inline void RelaxedOperator::update_h_max_supporter()
121{
122 assert(!unsatisfied_preconditions);
123 for (size_t i = 0; i < preconditions.size(); ++i)
124 if (preconditions[i]->h_max_cost > h_max_supporter->h_max_cost)
125 h_max_supporter = preconditions[i];
126 h_max_supporter_cost = h_max_supporter->h_max_cost;
127}
128} // namespace lm_cut_heuristic
129
130#endif