diff --git a/src/search/CMakeLists.txt b/src/search/CMakeLists.txt index 75ca24baac..620b6f220d 100644 --- a/src/search/CMakeLists.txt +++ b/src/search/CMakeLists.txt @@ -706,7 +706,8 @@ create_fast_downward_library( create_fast_downward_library( NAME default_value_axioms_task - HELP "Task transformation adding axioms for the default value of derived variables" + HELP "Task transformation adding axioms describing under which " + "circumstances a derived variable is set to its default value." SOURCES tasks/default_value_axioms_task DEPENDS diff --git a/src/search/cartesian_abstractions/split_selector.cc b/src/search/cartesian_abstractions/split_selector.cc index 3ab6f32c92..d9a3b1c4fb 100644 --- a/src/search/cartesian_abstractions/split_selector.cc +++ b/src/search/cartesian_abstractions/split_selector.cc @@ -24,7 +24,8 @@ SplitSelector::SplitSelector( if (pick == PickSplit::MIN_HADD || pick == PickSplit::MAX_HADD) { additive_heuristic = utils::make_unique_ptr( - true, task, false, "h^add within CEGAR abstractions", + tasks::AxiomHandlingType::APPROXIMATE_NEGATIVE, task, + false, "h^add within CEGAR abstractions", utils::Verbosity::SILENT); additive_heuristic->compute_heuristic_for_cegar( task_proxy.get_initial_state()); diff --git a/src/search/cartesian_abstractions/subtask_generators.cc b/src/search/cartesian_abstractions/subtask_generators.cc index c55f34e901..836a077184 100644 --- a/src/search/cartesian_abstractions/subtask_generators.cc +++ b/src/search/cartesian_abstractions/subtask_generators.cc @@ -35,7 +35,8 @@ class SortFactsByIncreasingHaddValues { explicit SortFactsByIncreasingHaddValues( const shared_ptr &task) : hadd(utils::make_unique_ptr( - true, task, false, "h^add within CEGAR abstractions", + tasks::AxiomHandlingType::APPROXIMATE_NEGATIVE, task, + false, "h^add within CEGAR abstractions", utils::Verbosity::SILENT)) { TaskProxy task_proxy(*task); hadd->compute_heuristic_for_cegar(task_proxy.get_initial_state()); diff --git a/src/search/heuristics/additive_heuristic.cc b/src/search/heuristics/additive_heuristic.cc index 1bd330a315..007d3c64fd 100644 --- a/src/search/heuristics/additive_heuristic.cc +++ b/src/search/heuristics/additive_heuristic.cc @@ -14,11 +14,11 @@ namespace additive_heuristic { const int AdditiveHeuristic::MAX_COST_VALUE; AdditiveHeuristic::AdditiveHeuristic( - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const shared_ptr &transform, bool cache_estimates, const string &description, utils::Verbosity verbosity) : RelaxationHeuristic( - simple_default_value_axioms, transform, cache_estimates, description, + axiom_handling, transform, cache_estimates, description, verbosity), did_write_overflow_warning(false) { if (log.is_at_least_normal()) { diff --git a/src/search/heuristics/additive_heuristic.h b/src/search/heuristics/additive_heuristic.h index 44bf1f5d76..89fd1cbf6d 100644 --- a/src/search/heuristics/additive_heuristic.h +++ b/src/search/heuristics/additive_heuristic.h @@ -66,7 +66,7 @@ class AdditiveHeuristic : public relaxation_heuristic::RelaxationHeuristic { int compute_add_and_ff(const State &state); public: AdditiveHeuristic( - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const std::shared_ptr &transform, bool cache_estimates, const std::string &description, utils::Verbosity verbosity); diff --git a/src/search/heuristics/cea_heuristic.cc b/src/search/heuristics/cea_heuristic.cc index 6350382002..d950bfb4b8 100644 --- a/src/search/heuristics/cea_heuristic.cc +++ b/src/search/heuristics/cea_heuristic.cc @@ -5,7 +5,6 @@ #include "../plugins/plugin.h" #include "../task_utils/task_properties.h" -#include "../tasks/default_value_axioms_task.h" #include "../utils/logging.h" #include @@ -410,11 +409,11 @@ int ContextEnhancedAdditiveHeuristic::compute_heuristic( } ContextEnhancedAdditiveHeuristic::ContextEnhancedAdditiveHeuristic( - bool simple_default_value_axioms, const shared_ptr &transform, - bool cache_estimates, const string &description, - utils::Verbosity verbosity) + tasks::AxiomHandlingType axiom_handling, + const shared_ptr &transform, bool cache_estimates, + const string &description, utils::Verbosity verbosity) : Heuristic(tasks::get_default_value_axioms_task_if_needed( - transform, simple_default_value_axioms), + transform, axiom_handling), cache_estimates, description, verbosity), min_action_cost(task_properties::get_min_operator_cost(task_proxy)) { if (log.is_at_least_normal()) { @@ -454,12 +453,7 @@ class ContextEnhancedAdditiveHeuristicFeature ContextEnhancedAdditiveHeuristicFeature() : TypedFeature("cea") { document_title("Context-enhanced additive heuristic"); - add_option( - "simple_default_value_axioms", - "For derived variables that need negated axioms, introduce the trivial" - "rule with an empty body. This makes the heuristic weaker but avoids" - "a potentially expensive precomputation.", - "false"); + tasks::add_axioms_option_to_feature(*this); add_heuristic_options_to_feature(*this, "cea"); document_language_support("action costs", "supported"); @@ -480,7 +474,7 @@ class ContextEnhancedAdditiveHeuristicFeature create_component(const plugins::Options &opts, const utils::Context &) const override { return plugins::make_shared_from_arg_tuples( - opts.get("simple_default_value_axioms"), + tasks::get_axioms_arguments_from_options(opts), get_heuristic_arguments_from_options(opts) ); } diff --git a/src/search/heuristics/cea_heuristic.h b/src/search/heuristics/cea_heuristic.h index 59f4697a45..3181bee0c4 100644 --- a/src/search/heuristics/cea_heuristic.h +++ b/src/search/heuristics/cea_heuristic.h @@ -6,6 +6,7 @@ #include "../heuristic.h" #include "../algorithms/priority_queues.h" +#include "../tasks/default_value_axioms_task.h" #include @@ -51,7 +52,7 @@ class ContextEnhancedAdditiveHeuristic : public Heuristic { virtual int compute_heuristic(const State &ancestor_state) override; public: ContextEnhancedAdditiveHeuristic( - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const std::shared_ptr &transform, bool cache_estimates, const std::string &description, utils::Verbosity verbosity); diff --git a/src/search/heuristics/cg_heuristic.cc b/src/search/heuristics/cg_heuristic.cc index 80deac0a0f..b1bf650398 100644 --- a/src/search/heuristics/cg_heuristic.cc +++ b/src/search/heuristics/cg_heuristic.cc @@ -5,7 +5,6 @@ #include "../plugins/plugin.h" #include "../task_utils/task_properties.h" -#include "../tasks/default_value_axioms_task.h" #include "../utils/logging.h" #include @@ -18,12 +17,12 @@ using namespace domain_transition_graph; namespace cg_heuristic { CGHeuristic::CGHeuristic( - int max_cache_size, bool simple_default_value_axioms, + int max_cache_size, tasks::AxiomHandlingType axiom_handling, const shared_ptr &transform, bool cache_estimates, const string &description, utils::Verbosity verbosity) : Heuristic(tasks::get_default_value_axioms_task_if_needed( - transform, simple_default_value_axioms), + transform, axiom_handling), cache_estimates, description, verbosity), cache_hits(0), cache_misses(0), @@ -299,12 +298,7 @@ class CGHeuristicFeature "maximum number of cached entries per variable (set to 0 to disable cache)", "1000000", plugins::Bounds("0", "infinity")); - add_option( - "simple_default_value_axioms", - "For derived variables that need negated axioms, introduce the trivial" - "rule with an empty body. This makes the heuristic weaker but avoids" - "a potentially expensive precomputation.", - "false"); + tasks::add_axioms_option_to_feature(*this); add_heuristic_options_to_feature(*this, "cg"); document_language_support("action costs", "supported"); @@ -326,7 +320,7 @@ class CGHeuristicFeature const utils::Context &) const override { return plugins::make_shared_from_arg_tuples( opts.get("max_cache_size"), - opts.get("simple_default_value_axioms"), + tasks::get_axioms_arguments_from_options(opts), get_heuristic_arguments_from_options(opts) ); } diff --git a/src/search/heuristics/cg_heuristic.h b/src/search/heuristics/cg_heuristic.h index 4920d0a651..7252e1607c 100644 --- a/src/search/heuristics/cg_heuristic.h +++ b/src/search/heuristics/cg_heuristic.h @@ -4,6 +4,7 @@ #include "../heuristic.h" #include "../algorithms/priority_queues.h" +#include "../tasks/default_value_axioms_task.h" #include #include @@ -45,7 +46,7 @@ class CGHeuristic : public Heuristic { public: explicit CGHeuristic( int max_cache_size, - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_hanlding, const std::shared_ptr &transform, bool cache_estimates, const std::string &description, utils::Verbosity verbosity); diff --git a/src/search/heuristics/ff_heuristic.cc b/src/search/heuristics/ff_heuristic.cc index 92e5e25ef3..fc4d244ccd 100644 --- a/src/search/heuristics/ff_heuristic.cc +++ b/src/search/heuristics/ff_heuristic.cc @@ -12,11 +12,11 @@ using namespace std; namespace ff_heuristic { // construction and destruction FFHeuristic::FFHeuristic( - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const shared_ptr &transform, bool cache_estimates, const string &description, utils::Verbosity verbosity) : AdditiveHeuristic( - simple_default_value_axioms, transform, cache_estimates, description, + axiom_handling, transform, cache_estimates, description, verbosity), relaxed_plan(task_proxy.get_operators().size(), false) { if (log.is_at_least_normal()) { diff --git a/src/search/heuristics/ff_heuristic.h b/src/search/heuristics/ff_heuristic.h index c1b7482cb8..99aff9ca89 100644 --- a/src/search/heuristics/ff_heuristic.h +++ b/src/search/heuristics/ff_heuristic.h @@ -33,7 +33,7 @@ class FFHeuristic : public additive_heuristic::AdditiveHeuristic { virtual int compute_heuristic(const State &ancestor_state) override; public: FFHeuristic( - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const std::shared_ptr &transform, bool cache_estimates, const std::string &description, utils::Verbosity verbosity); diff --git a/src/search/heuristics/max_heuristic.cc b/src/search/heuristics/max_heuristic.cc index d7f2c8567f..b9e134a64e 100644 --- a/src/search/heuristics/max_heuristic.cc +++ b/src/search/heuristics/max_heuristic.cc @@ -23,11 +23,11 @@ namespace max_heuristic { // construction and destruction HSPMaxHeuristic::HSPMaxHeuristic( - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const shared_ptr &transform, bool cache_estimates, const string &description, utils::Verbosity verbosity) : RelaxationHeuristic( - simple_default_value_axioms, transform, cache_estimates, description, + axiom_handling, transform, cache_estimates, description, verbosity) { if (log.is_at_least_normal()) { log << "Initializing HSP max heuristic..." << endl; diff --git a/src/search/heuristics/max_heuristic.h b/src/search/heuristics/max_heuristic.h index 2529fdaa60..67196b6b64 100644 --- a/src/search/heuristics/max_heuristic.h +++ b/src/search/heuristics/max_heuristic.h @@ -34,7 +34,7 @@ class HSPMaxHeuristic : public relaxation_heuristic::RelaxationHeuristic { virtual int compute_heuristic(const State &ancestor_state) override; public: HSPMaxHeuristic( - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const std::shared_ptr &transform, bool cache_estimates, const std::string &description, utils::Verbosity verbosity); diff --git a/src/search/heuristics/relaxation_heuristic.cc b/src/search/heuristics/relaxation_heuristic.cc index 10b998227f..723dcc3798 100644 --- a/src/search/heuristics/relaxation_heuristic.cc +++ b/src/search/heuristics/relaxation_heuristic.cc @@ -2,7 +2,6 @@ #include "../plugins/plugin.h" #include "../task_utils/task_properties.h" -#include "../tasks/default_value_axioms_task.h" #include "../utils/collections.h" #include "../utils/logging.h" #include "../utils/timer.h" @@ -37,30 +36,26 @@ UnaryOperator::UnaryOperator( void add_relaxation_heuristic_options_to_feature( plugins::Feature &feature, const string &description) { - feature.add_option( - "simple_default_value_axioms", - "For derived variables that need negated axioms, introduce the trivial" - "rule with an empty body. This makes the heuristic weaker but avoids" - "a potentially expensive precomputation.", - "false"); + tasks::add_axioms_option_to_feature(feature); add_heuristic_options_to_feature(feature, description); } -tuple, bool, string, utils::Verbosity> +tuple, bool, string, + utils::Verbosity> get_relaxation_heuristic_arguments_from_options(const plugins::Options &opts) { return tuple_cat( - make_tuple(opts.get("simple_default_value_axioms")), + tasks::get_axioms_arguments_from_options(opts), get_heuristic_arguments_from_options(opts)); } // construction and destruction RelaxationHeuristic::RelaxationHeuristic( - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const shared_ptr &transform, bool cache_estimates, const string &description, utils::Verbosity verbosity) : Heuristic(tasks::get_default_value_axioms_task_if_needed( - transform, simple_default_value_axioms), + transform, axiom_handling), cache_estimates, description, verbosity) { // Build propositions. propositions.resize(task_properties::get_num_facts(task_proxy)); diff --git a/src/search/heuristics/relaxation_heuristic.h b/src/search/heuristics/relaxation_heuristic.h index 5853b87d98..87880e4d06 100644 --- a/src/search/heuristics/relaxation_heuristic.h +++ b/src/search/heuristics/relaxation_heuristic.h @@ -5,6 +5,7 @@ #include "../heuristic.h" +#include "../tasks/default_value_axioms_task.h" #include "../utils/collections.h" #include @@ -111,7 +112,7 @@ class RelaxationHeuristic : public Heuristic { Proposition *get_proposition(const FactProxy &fact); public: RelaxationHeuristic( - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const std::shared_ptr &transform, bool cache_estimates, const std::string &description, utils::Verbosity verbosity); @@ -121,8 +122,8 @@ class RelaxationHeuristic : public Heuristic { extern void add_relaxation_heuristic_options_to_feature( plugins::Feature &feature, const std::string &description); -extern std::tuple< - bool, std::shared_ptr, bool, std::string, utils::Verbosity> +extern std::tuple, + bool, std::string, utils::Verbosity> get_relaxation_heuristic_arguments_from_options(const plugins::Options &opts); } #endif diff --git a/src/search/landmarks/landmark_cost_partitioning_heuristic.cc b/src/search/landmarks/landmark_cost_partitioning_heuristic.cc index 87edb4f4bf..cb2a99b16c 100644 --- a/src/search/landmarks/landmark_cost_partitioning_heuristic.cc +++ b/src/search/landmarks/landmark_cost_partitioning_heuristic.cc @@ -18,13 +18,13 @@ namespace landmarks { LandmarkCostPartitioningHeuristic::LandmarkCostPartitioningHeuristic( const shared_ptr &lm_factory, bool pref, bool prog_goal, bool prog_gn, bool prog_r, - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const shared_ptr &transform, bool cache_estimates, const string &description, utils::Verbosity verbosity, CostPartitioningMethod cost_partitioning, bool alm, lp::LPSolverType lpsolver) : LandmarkHeuristic( - simple_default_value_axioms, pref, transform, cache_estimates, description, verbosity) { + axiom_handling, pref, transform, cache_estimates, description, verbosity) { if (log.is_at_least_normal()) { log << "Initializing landmark cost partitioning heuristic..." << endl; } diff --git a/src/search/landmarks/landmark_cost_partitioning_heuristic.h b/src/search/landmarks/landmark_cost_partitioning_heuristic.h index 10cde9c2b6..119b8d9a2e 100644 --- a/src/search/landmarks/landmark_cost_partitioning_heuristic.h +++ b/src/search/landmarks/landmark_cost_partitioning_heuristic.h @@ -26,7 +26,7 @@ class LandmarkCostPartitioningHeuristic : public LandmarkHeuristic { LandmarkCostPartitioningHeuristic( const std::shared_ptr &lm_factory, bool pref, bool prog_goal, bool prog_gn, bool prog_r, - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const std::shared_ptr &transform, bool cache_estimates, const std::string &description, utils::Verbosity verbosity, diff --git a/src/search/landmarks/landmark_heuristic.cc b/src/search/landmarks/landmark_heuristic.cc index ec4baeaca8..73a04dfcbe 100644 --- a/src/search/landmarks/landmark_heuristic.cc +++ b/src/search/landmarks/landmark_heuristic.cc @@ -7,7 +7,6 @@ #include "../plugins/plugin.h" #include "../task_utils/successor_generator.h" #include "../tasks/cost_adapted_task.h" -#include "../tasks/default_value_axioms_task.h" #include "../tasks/root_task.h" #include "../utils/markup.h" @@ -15,12 +14,11 @@ using namespace std; namespace landmarks { LandmarkHeuristic::LandmarkHeuristic( - bool simple_default_value_axioms, - bool use_preferred_operators, + tasks::AxiomHandlingType axiom_handling, bool use_preferred_operators, const shared_ptr &transform, bool cache_estimates, const string &description, utils::Verbosity verbosity) : Heuristic(tasks::get_default_value_axioms_task_if_needed( - transform, simple_default_value_axioms), + transform, axiom_handling), cache_estimates, description, verbosity), use_preferred_operators(use_preferred_operators), successor_generator(nullptr) { @@ -40,7 +38,7 @@ void LandmarkHeuristic::initialize( && dynamic_cast(task.get()) == nullptr) { cerr << "The landmark heuristics currently only support " << "task transformations that modify the operator costs " - << "or add negated axioms. See issues 845 and 686 " + << "or add negated axioms. See issues 845, 686 and 454 " << "for details." << endl; utils::exit_with(utils::ExitCode::SEARCH_UNSUPPORTED); } @@ -230,20 +228,16 @@ void add_landmark_heuristic_options_to_feature( "prog_gn", "Use greedy-necessary ordering progression.", "true"); feature.add_option( "prog_r", "Use reasonable ordering progression.", "true"); - feature.add_option( - "simple_default_value_axioms", - "For derived variables that need negated axioms, introduce the trivial" - "rule with an empty body. This makes the heuristic weaker but avoids" - "a potentially expensive precomputation.", - "false"); + tasks::add_axioms_option_to_feature(feature); add_heuristic_options_to_feature(feature, description); feature.document_property("preferred operators", "yes (if enabled; see ``pref`` option)"); } -tuple, bool, bool, bool, bool, bool, - shared_ptr, bool, string, utils::Verbosity> +tuple, bool, bool, bool, bool, + tasks::AxiomHandlingType, shared_ptr, bool, string, + utils::Verbosity> get_landmark_heuristic_arguments_from_options( const plugins::Options &opts) { return tuple_cat( @@ -252,9 +246,8 @@ get_landmark_heuristic_arguments_from_options( opts.get("pref"), opts.get("prog_goal"), opts.get("prog_gn"), - opts.get("prog_r"), - opts.get("simple_default_value_axioms") - ), + opts.get("prog_r")), + tasks::get_axioms_arguments_from_options(opts), get_heuristic_arguments_from_options(opts)); } } diff --git a/src/search/landmarks/landmark_heuristic.h b/src/search/landmarks/landmark_heuristic.h index 9a098967ae..f5e1ac83fd 100644 --- a/src/search/landmarks/landmark_heuristic.h +++ b/src/search/landmarks/landmark_heuristic.h @@ -3,6 +3,8 @@ # include "../heuristic.h" +#include "../tasks/default_value_axioms_task.h" + class ConstBitsetView; namespace successor_generator { @@ -44,7 +46,7 @@ class LandmarkHeuristic : public Heuristic { virtual int compute_heuristic(const State &ancestor_state) override; public: LandmarkHeuristic( - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, bool use_preferred_operators, const std::shared_ptr &transform, bool cache_estimates, const std::string &description, @@ -64,8 +66,9 @@ class LandmarkHeuristic : public Heuristic { extern void add_landmark_heuristic_options_to_feature( plugins::Feature &feature, const std::string &description); extern std::tuple, bool, bool, bool, - bool, bool, std::shared_ptr, bool, - std::string, utils::Verbosity> + bool, tasks::AxiomHandlingType, + std::shared_ptr, bool, std::string, + utils::Verbosity> get_landmark_heuristic_arguments_from_options( const plugins::Options &opts); } diff --git a/src/search/landmarks/landmark_sum_heuristic.cc b/src/search/landmarks/landmark_sum_heuristic.cc index c533fe3115..5304de7793 100644 --- a/src/search/landmarks/landmark_sum_heuristic.cc +++ b/src/search/landmarks/landmark_sum_heuristic.cc @@ -33,11 +33,11 @@ static bool are_dead_ends_reliable( LandmarkSumHeuristic::LandmarkSumHeuristic( const shared_ptr &lm_factory, bool pref, bool prog_goal, bool prog_gn, bool prog_r, - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const shared_ptr &transform, bool cache_estimates, const string &description, utils::Verbosity verbosity) : LandmarkHeuristic( - simple_default_value_axioms, pref, transform, cache_estimates, + axiom_handling, pref, transform, cache_estimates, description, verbosity), dead_ends_reliable( are_dead_ends_reliable(lm_factory, task_proxy)) { diff --git a/src/search/landmarks/landmark_sum_heuristic.h b/src/search/landmarks/landmark_sum_heuristic.h index e3e370cf46..958750baad 100644 --- a/src/search/landmarks/landmark_sum_heuristic.h +++ b/src/search/landmarks/landmark_sum_heuristic.h @@ -19,7 +19,7 @@ class LandmarkSumHeuristic : public LandmarkHeuristic { LandmarkSumHeuristic( const std::shared_ptr &lm_factory, bool pref, bool prog_goal, bool prog_gn, bool prog_r, - bool simple_default_value_axioms, + tasks::AxiomHandlingType axiom_handling, const std::shared_ptr &transform, bool cache_estimates, const std::string &description, utils::Verbosity verbosity); diff --git a/src/search/tasks/default_value_axioms_task.cc b/src/search/tasks/default_value_axioms_task.cc index c022ed9425..985cf6eedb 100644 --- a/src/search/tasks/default_value_axioms_task.cc +++ b/src/search/tasks/default_value_axioms_task.cc @@ -16,9 +16,9 @@ using utils::ExitCode; namespace tasks { DefaultValueAxiomsTask::DefaultValueAxiomsTask( const shared_ptr &parent, - bool simple_default_axioms) + AxiomHandlingType axiom_handling) : DelegatingTask(parent), - simple_default_value_axioms(simple_default_axioms), + axiom_handling(axiom_handling), default_value_axioms_start_index(parent->get_num_axioms()) { TaskProxy task_proxy(*parent); @@ -61,7 +61,7 @@ DefaultValueAxiomsTask::DefaultValueAxiomsTask( vector> sccs; vector *> var_to_scc; // We don't need the sccs if we set axioms "v=default <- {}" everywhere. - if (!simple_default_axioms) { + if (axiom_handling == AxiomHandlingType::APPROXIMATE_NEGATIVE_CYCLES) { sccs = sccs::compute_maximal_sccs(nondefault_dependencies); var_to_scc = vector *>( task_proxy.get_variables().size(), nullptr); @@ -80,7 +80,8 @@ DefaultValueAxiomsTask::DefaultValueAxiomsTask( int default_value = task_proxy.get_variables()[var].get_default_axiom_value(); - if (simple_default_axioms || var_to_scc[var]->size() > 1) { + if (axiom_handling == AxiomHandlingType::APPROXIMATE_NEGATIVE + || var_to_scc[var]->size() > 1) { /* If there is a cyclic dependency between several derived variables, the "obvious" way of negating the formula @@ -176,7 +177,8 @@ unordered_set DefaultValueAxiomsTask::get_default_value_needed( pair) doesn't depend on anything. */ if ((default_value) && - (simple_default_value_axioms || var_to_scc[var]->size() > 1)) { + (axiom_handling == AxiomHandlingType::APPROXIMATE_NEGATIVE + || var_to_scc[var]->size() > 1)) { continue; } @@ -386,12 +388,38 @@ int DefaultValueAxiomsTask::get_num_axioms() const { shared_ptr get_default_value_axioms_task_if_needed( const shared_ptr &task, - bool simple_default_value_axioms) { + AxiomHandlingType axiom_handling) { TaskProxy proxy(*task); if (task_properties::has_axioms(proxy)) { return make_shared( - DefaultValueAxiomsTask(task, simple_default_value_axioms)); + DefaultValueAxiomsTask(task, axiom_handling)); } return task; } + +void add_axioms_option_to_feature(plugins::Feature &feature) { + feature.add_option( + "axioms", + "How to compute axioms that describe how the negated " + "(=default) value of a derived variable can be achieved.", + "approximate_negative_cycles"); +} +std::tuple get_axioms_arguments_from_options( + const plugins::Options &opts) { + return make_tuple( + opts.get("axioms")); +} + +static plugins::TypedEnumPlugin _enum_plugin({ + {"approximate_negative", + "Overapproximate negated axioms for all derived variables by " + "setting an empty condition, indicating the default value can " + "always be achieved for free."}, + {"approximate_negative_cycles", + "Overapproximate negated axioms for all derived variables which " + "have cyclic dependencies by setting an empty condition, " + "indicating the default value can always be achieved for free." + "For all other derived variables, the negated axioms are computed" + "exactly."} + }); } diff --git a/src/search/tasks/default_value_axioms_task.h b/src/search/tasks/default_value_axioms_task.h index 624b845afa..e6780d756e 100644 --- a/src/search/tasks/default_value_axioms_task.h +++ b/src/search/tasks/default_value_axioms_task.h @@ -3,11 +3,9 @@ #include "delegating_task.h" -#include +#include "../plugins/plugin.h" -namespace plugins { -class Options; -} +#include /* This task transformation adds explicit axioms for how the default value @@ -38,6 +36,10 @@ class Options; */ namespace tasks { +enum class AxiomHandlingType { + APPROXIMATE_NEGATIVE, APPROXIMATE_NEGATIVE_CYCLES +}; + struct DefaultValueAxiom { FactPair head; std::vector condition; @@ -47,7 +49,7 @@ struct DefaultValueAxiom { }; class DefaultValueAxiomsTask : public DelegatingTask { - bool simple_default_value_axioms; + AxiomHandlingType axiom_handling; std::vector default_value_axioms; int default_value_axioms_start_index; @@ -65,7 +67,7 @@ class DefaultValueAxiomsTask : public DelegatingTask { public: explicit DefaultValueAxiomsTask( const std::shared_ptr &parent, - bool simple_default_axioms); + AxiomHandlingType axiom_handling); virtual ~DefaultValueAxiomsTask() override = default; virtual int get_operator_cost(int index, bool is_axiom) const override; @@ -86,7 +88,10 @@ class DefaultValueAxiomsTask : public DelegatingTask { extern std::shared_ptr get_default_value_axioms_task_if_needed( const std::shared_ptr &task, - bool simple_default_value_axioms); + AxiomHandlingType axiom_handling); +extern void add_axioms_option_to_feature(plugins::Feature &feature); +extern std::tuple get_axioms_arguments_from_options( + const plugins::Options &opts); } #endif