diff --git a/src/search/landmarks/landmark_graph.cc b/src/search/landmarks/landmark_graph.cc index 4ce14e2ebf..5f6a8bf066 100644 --- a/src/search/landmarks/landmark_graph.cc +++ b/src/search/landmarks/landmark_graph.cc @@ -57,6 +57,11 @@ LandmarkNode &LandmarkGraph::get_disjunctive_landmark(const FactPair &fact) cons return *(disjunctive_landmarks_to_nodes.find(fact)->second); } +const vector &LandmarkGraph::get_conjunctive_landmarks( + const FactPair &fact) const { + assert(contains_conjunctive_landmark(fact)); + return conjunctive_landmarks_to_nodes.find(fact)->second; +} bool LandmarkGraph::contains_simple_landmark(const FactPair &lm) const { return simple_landmarks_to_nodes.count(lm) != 0; @@ -66,6 +71,10 @@ bool LandmarkGraph::contains_disjunctive_landmark(const FactPair &lm) const { return disjunctive_landmarks_to_nodes.count(lm) != 0; } +bool LandmarkGraph::contains_conjunctive_landmark(const FactPair &lm) const { + return conjunctive_landmarks_to_nodes.count(lm) != 0; +} + bool LandmarkGraph::contains_overlapping_disjunctive_landmark( const set &lm) const { // Test whether ONE of the facts is present in some disjunctive landmark. @@ -118,6 +127,15 @@ LandmarkNode &LandmarkGraph::add_landmark(Landmark &&landmark) { } ++num_disjunctive_landmarks; } else if (lm.conjunctive) { + for (const FactPair &lm_fact : lm.facts) { + auto it = conjunctive_landmarks_to_nodes.find(lm_fact); + if (it == conjunctive_landmarks_to_nodes.end()) { + conjunctive_landmarks_to_nodes.emplace( + lm_fact, vector{new_node_p}); + } else { + (it->second).push_back(new_node_p); + } + } ++num_conjunctive_landmarks; } else { simple_landmarks_to_nodes.emplace(lm.facts.front(), new_node_p); @@ -144,6 +162,14 @@ void LandmarkGraph::remove_node_occurrences(LandmarkNode *node) { } } else if (landmark.conjunctive) { --num_conjunctive_landmarks; + for (const FactPair &lm_fact : landmark.facts) { + vector *conjunctive_landmarks_vector = + &(conjunctive_landmarks_to_nodes.find(lm_fact)->second); + auto it = find(conjunctive_landmarks_vector->begin(), + conjunctive_landmarks_vector->end(), node); + assert(it != conjunctive_landmarks_vector->end()); + conjunctive_landmarks_vector->erase(it); + } } else { simple_landmarks_to_nodes.erase(landmark.facts[0]); } diff --git a/src/search/landmarks/landmark_graph.h b/src/search/landmarks/landmark_graph.h index f198bba02b..88941122f6 100644 --- a/src/search/landmarks/landmark_graph.h +++ b/src/search/landmarks/landmark_graph.h @@ -77,6 +77,7 @@ class LandmarkGraph { utils::HashMap simple_landmarks_to_nodes; utils::HashMap disjunctive_landmarks_to_nodes; + utils::HashMap> conjunctive_landmarks_to_nodes; Nodes nodes; void remove_node_occurrences(LandmarkNode *node); @@ -118,6 +119,9 @@ class LandmarkGraph { /* This is needed only by landmark graph factories and will disappear when moving landmark graph creation there. */ LandmarkNode &get_disjunctive_landmark(const FactPair &fact) const; + // TODO: comment? + const std::vector &get_conjunctive_landmarks( + const FactPair &fact) const; /* This is needed only by landmark graph factories and will disappear when moving landmark graph creation there. It is not needed by @@ -125,6 +129,8 @@ class LandmarkGraph { bool contains_simple_landmark(const FactPair &lm) const; /* Only used internally. */ bool contains_disjunctive_landmark(const FactPair &lm) const; + // TODO: comment? + bool contains_conjunctive_landmark(const FactPair &lm) const; /* This is needed only by landmark graph factories and will disappear when moving landmark graph creation there. It is not needed by HMLandmarkFactory*/ diff --git a/src/search/landmarks/landmark_heuristic.cc b/src/search/landmarks/landmark_heuristic.cc index b03c119a13..4f234e257a 100644 --- a/src/search/landmarks/landmark_heuristic.cc +++ b/src/search/landmarks/landmark_heuristic.cc @@ -118,12 +118,7 @@ void LandmarkHeuristic::compute_landmark_graph( void LandmarkHeuristic::generate_preferred_operators( const State &state, ConstBitsetView &future) { - /* - Find operators that achieve future landmarks. - TODO: Conjunctive landmarks are ignored in *lm_graph->get_node(...)*, so - they are ignored when computing preferred operators. We consider this - a bug and want to fix it in issue1072. - */ + // Find operators that achieve future landmarks. assert(successor_generator); vector applicable_operators; successor_generator->generate_applicable_ops(state, applicable_operators); @@ -132,13 +127,27 @@ void LandmarkHeuristic::generate_preferred_operators( OperatorProxy op = task_proxy.get_operators()[op_id]; EffectsProxy effects = op.get_effects(); for (EffectProxy effect : effects) { - if (!does_fire(effect, state)) + if (!does_fire(effect, state)) { + continue; + } + FactPair fact = effect.get_fact().get_pair(); + if (state[fact.var].get_value() == fact.value) { continue; - FactProxy fact_proxy = effect.get_fact(); - LandmarkNode *lm_node = lm_graph->get_node(fact_proxy.get_pair()); + } + LandmarkNode *lm_node = lm_graph->get_node(fact); if (lm_node && future.test(lm_node->get_id())) { set_preferred(op); } + if (lm_graph->contains_conjunctive_landmark(fact)) { + vector conjunctive_landmarks = + lm_graph->get_conjunctive_landmarks(fact); + for (auto conj_lm : conjunctive_landmarks) { + if (future.test(conj_lm->get_id())) { + set_preferred(op); + break; + } + } + } } } }