├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── doc ├── antlrHDDL-cleaned.g4 ├── antlrHDDL.g4 ├── hddl-cleaned.y ├── hddl-token-cleaned.l ├── hddl-token.l ├── hddl.y └── parser-output-format.md ├── makefile ├── src ├── .gitignore ├── cwa.cpp ├── cwa.hpp ├── domain.cpp ├── domain.hpp ├── hddl-token.l ├── hddl.y ├── hddlWriter.cpp ├── hddlWriter.hpp ├── hpdlWriter.cpp ├── hpdlWriter.hpp ├── htn2stripsWriter.cpp ├── htn2stripsWriter.hpp ├── main.cpp ├── options.ggo ├── orderingDecomposition.cpp ├── orderingDecomposition.hpp ├── output.cpp ├── output.hpp ├── parametersplitting.cpp ├── parametersplitting.hpp ├── parsetree.cpp ├── parsetree.hpp ├── plan.cpp ├── plan.hpp ├── properties.cpp ├── properties.hpp ├── shopWriter.cpp ├── shopWriter.hpp ├── sortexpansion.cpp ├── sortexpansion.hpp ├── typeof.cpp ├── typeof.hpp ├── util.cpp ├── util.hpp ├── verification_encoding.cpp ├── verification_encoding.hpp ├── verify.cpp └── verify.hpp └── tests ├── conditional-effect-problem.hddl ├── conditional-effect.hddl ├── conditional-effect.htn ├── conditional-test-problem.hddl ├── conditional-test.hddl ├── constant-in-method-test-problem.hddl ├── constant-in-method-test.hddl ├── effect-precedence-problem.hddl ├── effect-precedence.hddl ├── empty-d.hddl ├── empty-p.hddl ├── empty.plan ├── entertainment-01.plan ├── interleaving-d.hddl ├── interleaving-p.hddl ├── method-effect-problem.hddl ├── method-effect.hddl ├── method-effect.htn ├── minecraft-costs-constant.hddl ├── minecraft-costs-problem.hddl ├── minecraft-costs.hddl ├── plan-for-transport-pfile01-non-existing-method.txt ├── plan-for-transport-pfile01-notop.txt ├── plan-for-transport-pfile01-total-order.txt ├── plan-for-transport-pfile01-wrong.txt ├── plan-for-transport-pfile01.txt ├── rover01.plan ├── um-translog-01.plan ├── woodworking-00.plan └── zenotravel-01.plan /.gitignore: -------------------------------------------------------------------------------- 1 | for-debugging/ 2 | pandaPIparser 3 | *.pddl 4 | *.sas 5 | *.htn 6 | *.hddl 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018-2021, Gregor Behnke 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # More Background Information 2 | 3 | We've put together a website with the history of all planning systems of the PANDA family, links to all relevant software projects, and further background information including pointers explaining the techniques deployed by the respective systems. 4 | 5 | - You find it on https://panda-planner-dev.github.io/ 6 | - or, as a forward, on http://panda.hierarchical-task.net 7 | 8 | 9 | # pandaPIparser 10 | 11 | This is the parsing utility of the pandaPI planning system. It is designed to parse HTN planning problems. Its main (and currently only) input language is HDDL (see the following [paper](http://www.uni-ulm.de/fileadmin/website_uni_ulm/iui.inst.090/Publikationen/2019/Hoeller2019HDDL.pdf)). 12 | 13 | If you use pandaPIparser in any of your published work, we would kindly ask you to cite us (see Reference below). 14 | 15 | 16 | ## Capabilities 17 | 18 | The parser can currently produce two different output formats: 19 | 20 | 1. pandaPI's internal numeric format for lifted HTN planning problems 21 | 2. (J)SHOP2's input language. 22 | 3. HPDL by Juan Fernández Olivares 23 | 24 | Note that the translation into (J)SHOP2 is necessarily incomplete as (J)SHOP2 cannot express arbitrary partial orders in its ordering constraints. For example a method with the five subtasks (a,b,c,d,e) and the ordering constraints a < c, a < d, b < d, and b < e cannot be formulated in (J)SHOP2. 25 | 26 | **Note**: The pandaPIparser is currently case sensitive. I.e. it interprets HDDL in a case sensitive version. The plan verifier can be switched to lenient mode in which it will interpret a given plan in a case-insensitive way. 27 | 28 | ## Compilation 29 | To compile pandaPIparser you need g++, make, flex, and bison. No libraries are required. You need a recent version of bison (versions 3.7.2 and 3.5.1 are known to work) and flex at least in version 2.6. Your C++ compiler needs to support C++17. 30 | 31 | To create the executable, simply run `make -j` in the root folder, which will create an executable called `pandaPIparser` 32 | 33 | ### MacOS X 34 | 35 | If you are using MacOSX, the default versions of bison and flex are quite old. You need to install a recent version of bison and flex via brew. By default, the path for flex and bison is set to the most common location within a brew installation (which are `/opt/homebrew/opt/bison/bin/bison` and `/opt/homebrew/opt/flex/bin/flex`). If these paths are not correct for your system, you may alter them by changing the `BISON` and `FLEX` variables as follows: 36 | ``` 37 | BISON=/opt/homebrew/opt/bison/bin/bison FLEX=/opt/homebrew/opt/flex/bin/flex make -j 38 | ``` 39 | 40 | *Note* If you are using MacOSX, we compile the parser without the flags `-static` and `-static-libgcc` as static compilation does not work under MacOSX. This may slow down the parser, but it should not be significant. 41 | 42 | ### Debug Build 43 | 44 | If you require a debug build (which will cause the parser to output a lot of debugging information to `stdout`), you can call the target `make debug`. Be aware that you might have to do a full re-build for this to work properly, i.e., a `make -Bj debug`. 45 | 46 | 47 | ## Usage 48 | The parser is called with at least two arguments: the domain and the problem file. Both must be written in HDDL. 49 | 50 | ### Usage within PANDA 51 | The translation from HDDL to PANDA's internal file format is the default behaviour of pandaPIparser. 52 | By default, the parser will output the given instance in pandaPI's internal format on standard our. 53 | If you pass a third file name, pandaPIparser will instead output the internal representation of the instance to that file. 54 | As an example you can call 55 | 56 | ``` 57 | ./pandaPIParser transport.hddl pfile01.hddl transport-pfile01.htn 58 | ``` 59 | 60 | This will generate a file `transport-pfile01.htn` that contains a lifted, but machine readable version of the domain and problem that is read by the pandaPIgrounder. 61 | 62 | ### Usage for Compilation to (J)SHOP2 63 | pandaPIparser also offers to option to write the output to (J)SHOP2's input format. In order to do so add `-shop` as one of the command line arguments (the position does not matter). 64 | With `-shop` you may specify up to four files as command line arguments: the input domain, the input problem, the output domain, and the output problem. 65 | As an example consider 66 | 67 | ``` 68 | ./pandaPIParser --shop transport.hddl pfile01.hddl shop-transport.lisp shop-pfile01.lisp 69 | ``` 70 | 71 | Note that 72 | * pandaPIparser will shift some of the contents of the HDDL problem file to the (J)SHOP2 domain file. Most notably, pandaPIparser moves the initial task network of the HDDL problem into the (J)SHOP2 domain by compiling it into a method for a new abstract task `__top`. 73 | * any propositional goal will be ignored in the translation. 74 | * only constant action costs (i.e. integer valued ones that do not depend on parameters and state) are supported. 75 | * any action named `call` will be renamed to `_call`, as `call` is a keyword for (J)SHOP2. 76 | * current `forall` statements in preconditions are fully instantiated. 77 | 78 | 79 | ### Usage for Compilation to (J)SHOP1 80 | pandaPIparser also supports (J)SHOP1's output. This is essentially the same as the output for (J)SHOP2 with the only difference that underscores will be replaced by minuses and leading minuses are prepended with an `x`. 81 | To call the translator in this compatibility mode, use `--shop1` instead of `--shop` as the command line argument. 82 | 83 | 84 | ### Usage for Compilation to HPDL 85 | pandaPIparser also offers to option to write the output to HPDL. In order to do so add `--hpdl` as one of the command line arguments (the position does not matter). 86 | Parameter-wise `--hpdl` works exactly as `--shop` 87 | 88 | 89 | ## Contact 90 | If you have any issues with pandaPIparser -- or have any question relating to its use, please contact [Gregor Behnke](mailto:g.behnke@uva.nl). 91 | 92 | 93 | ## Reference 94 | If you would like to cite pandaPIparser, you may do so my referring to the following paper: 95 | 96 | {% raw %} 97 | ``` 98 | @inproceedings { Behnke2020Grounding, 99 | Title = {On Succinct Groundings of {HTN} Planning Problems}, 100 | Year = {2020}, 101 | Booktitle = {Proceedings of the 34th {AAAI} Conference on Artificial Intelligence ({AAAI} 2020)}, 102 | Publisher = {{AAAI Press}}, 103 | Author = {Behnke, Gregor and H{\"o}ller, Daniel and Schmid, Alexander and Bercher, Pascal and Biundo, Susanne} 104 | } 105 | ``` 106 | {% endraw %} 107 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /doc/antlrHDDL-cleaned.g4: -------------------------------------------------------------------------------- 1 | grammar antlrHDDL; 2 | 3 | /** 4 | * Created by Daniel Höller, Ulm University (daniel.hoeller@uni-ulm.de) 5 | * and Mario Schmautz, Ulm University (mario.schmautz@uni-ulm.de) [some refactoring & additions] 6 | * 7 | * - This file contains the grammar for the ANTLR parser generator 8 | * - It describes an extension of the Planning Domain Definition Language to describe hierarchical 9 | * planning problems like Hybrid Planning or Hierarchical Task Network planning. 10 | * - It is based on the PDDL 2.1 definition by Maria Fox & Derek Long (so far, only the non-temporal part) 11 | **/ 12 | 13 | // @IGNORE 14 | hddl_file : domain | problem; 15 | 16 | // 17 | // General Structure of a Domain Definition 18 | // 19 | // @MODIFIED 20 | // @LABEL {The domain definition has been extended by definitions for compound tasks and methods.} 21 | domain : '(' 'define' '(' 'domain' domain_symbol ')' 22 | require_def? 23 | type_def? 24 | const_def? 25 | predicates_def? 26 | comp_task_def* // @HIGHLIGHT 27 | method_def* // @HIGHLIGHT 28 | action_def* ')'; 29 | 30 | // @PDDL 31 | domain_symbol : NAME; 32 | 33 | // 34 | // Requirement Statement 35 | // 36 | // @PDDL 37 | require_def : '(' ':requirements' require_defs ')'; 38 | require_defs : REQUIRE_NAME+; 39 | 40 | // 41 | // Type Definition 42 | // 43 | // @PDDL 44 | type_def : '(' ':types' type_def_list ')'; 45 | type_def_list : NAME* | (new_types '-' var_type type_def_list) ; 46 | new_types : NAME+; 47 | 48 | // 49 | // Domain Constant Definition 50 | // 51 | // @PDDL 52 | const_def : '(' ':constants' typed_obj_list ')'; 53 | 54 | // 55 | // Predicate Definition 56 | // 57 | // @PDDL 58 | predicates_def : '(' ':predicates' atomic_formula_skeleton+ ')'; 59 | atomic_formula_skeleton : '(' predicate typed_var_list ')'; 60 | 61 | // 62 | // Task Definition 63 | // 64 | // @HDDL 65 | // @LABEL {Abstract tasks are defined similar to actions. To use preconditions and effects in the definition, 66 | // please add the requirement definition :htn-abstract-actions} 67 | comp_task_def : 68 | '(' ':task' task_def; 69 | 70 | task_def : task_symbol 71 | ':parameters' '(' typed_var_list ')' ')'; 72 | 73 | task_symbol : NAME; 74 | 75 | // 76 | // Method Definition 77 | // 78 | // @HDDL 79 | // @LABEL {In a pure HTN setting, methods consist of the definition of the abstract task they may decompose as well as the 80 | // resulting task network. The parameters of a method are supposed to include all parameters of the abstract task 81 | // that it decomposes as well as those of the tasks in its network of subtasks. By setting the :htn-method-pre-eff 82 | // requirement, one might use method preconditions and effects similar to the ones used in SHOP.} 83 | method_def : 84 | '(' ':method' method_symbol 85 | ':parameters' '(' typed_var_list ')' 86 | ':task' '(' task_symbol var_or_const* ')' 87 | (':precondition' gd)? 88 | tasknetwork_def; 89 | 90 | // 91 | // Task Definition 92 | // 93 | // @HDDL 94 | // @LABEL {The following definition of a task network is used in method definitions as well as in the problem definition 95 | // to define the intial task network. It contains the definition of a number of tasks as well sets of ordering 96 | // constraints, variable constraints between any method parameters. Please use the requirement :htn-causal-links 97 | // to include causal links into the model. When the keys :ordered-subtasks or :ordered-tasks are used, the 98 | // network is regarded to be totally ordered. In the other cases, ordering relations may be defined in the 99 | // respective section. To do so, the task definition includes an id for every task that can be referenced here. 100 | // They are also used to define causal links. Two dedicated ids "init" and "goal" can be used in causal link 101 | // definition to reference the initial state and the goal definition.} 102 | tasknetwork_def : 103 | ((':subtasks' | ':tasks' | ':ordered-subtasks' | ':ordered-tasks') subtask_defs)? 104 | ((':ordering' | ':order') ordering_defs)? 105 | (':constraints' constraint_defs)? 106 | ')'; 107 | 108 | method_symbol : NAME; 109 | 110 | // 111 | // Subtasks 112 | // 113 | // @HDDL 114 | // @LABEL {The subtask definition may contain one or more subtasks. The tasks consist of a task symbol as well as a 115 | // list of parameters. In case of a method's subnetwork, these parameters have to be included in the method's 116 | // parameters, in case of the initial task network, they have to be defined as constants in s0 or in a dedicated 117 | // parameter list (see definition of the initial task network). The tasks may start with an id that can 118 | // be used to define ordering constraints and causal links.} 119 | subtask_defs : '(' ')' | subtask_def | '(' 'and' subtask_def+ ')'; 120 | subtask_def : ('(' task_symbol var_or_const* ')' | '(' subtask_id '(' task_symbol var_or_const* ')' ')'); 121 | subtask_id : NAME; 122 | 123 | // 124 | // Ordering 125 | // 126 | // @HDDL 127 | // @LABEL {The ordering constraints are defined via the task ids. They have to induce a partial order.} 128 | ordering_defs : '(' ')' | ordering_def | '(' 'and' ordering_def+ ')'; 129 | ordering_def : '(' subtask_id '<' subtask_id ')'; 130 | 131 | // 132 | // Variable Constraits 133 | // 134 | // @HDDL 135 | // @LABEL {The variable constraints enable to codesignate or non-codesignate variables; or to enforce (or forbid) a 136 | // variable to have a certain type.} 137 | // @EXAMPLE {(= ?v1 ?v2)), (not (= ?v3 ?v4)) 138 | constraint_defs : '(' ')' | constraint_def | '(' 'and' constraint_def+ ')'; 139 | constraint_def : '(' ')' | '(' 'not' equallity var_or_const var_or_const')' ')' | equallity var_or_const var_or_const ')' ; 140 | 141 | 142 | // 143 | // Action Definition 144 | // 145 | // @MODIFIED 146 | // @LABEL {The original action definition of PDDL has been split up to reuse its body in the task definition.} 147 | action_def : 148 | '(' ':action' task_def 149 | (':precondition' gd)? 150 | (':effect' effect)? ')'; 151 | 152 | // 153 | // Goal Description 154 | // @LABEL {gd means "goal description". It is used to define goals and preconditions.} 155 | // 156 | // @MODIFIED 157 | gd : gd_empty | atomic_formula | gd_negation | gd_implication | gd_conjuction | gd_disjuction | gd_existential | gd_universal | gd_equality_constraint; 158 | 159 | 160 | gd_empty : '(' ')'; 161 | gd_conjuction : '(' 'and' gd* ')'; 162 | gd_disjuction : '(' 'or' gd* ')'; 163 | gd_negation : '(' 'not' gd ')'; 164 | gd_implication : '(' 'imply' gd gd ')'; // new 165 | gd_existential : '(' 'exists' '(' typed_var_list ')' gd ')'; 166 | gd_universal : '(' 'forall' '(' typed_var_list ')' gd ')'; 167 | 168 | gd_equality_constraint : equallity var_or_const var_or_const ')'; 169 | 170 | 171 | // 172 | // Effects 173 | // 174 | // @LABEL {In contrast to earlier versions of this grammar, nested conditional effects are now permitted. 175 | // This is not allowed in PDDL 2.1} 176 | effect : eff_empty | eff_conjunction | eff_universal | eff_conditional | literal; 177 | 178 | eff_empty : '(' ')'; 179 | eff_conjunction : '(' 'and' effect* ')'; 180 | eff_universal : '(' 'forall' '(' typed_var_list ')' effect ')'; 181 | eff_conditional : '(' 'when' gd effect ')'; 182 | 183 | literal : neg_atomic_formula | atomic_formula; 184 | neg_atomic_formula : '(' 'not' atomic_formula ')'; 185 | 186 | // 187 | // Basic Definitions 188 | // 189 | 190 | // @LABEL {Predicate and atom definition:} 191 | atomic_formula : '('predicate var_or_const*')'; 192 | predicate : NAME; 193 | 194 | // @LABEL {Special "predicate" for equallity:} 195 | equallity : '(' '=' | '(='; 196 | 197 | // @LABEL {Lists of typed variables and objects:} 198 | typed_var_list : typed_vars*; 199 | typed_obj_list : typed_objs*; 200 | 201 | // @LABEL {One or more variable names, followed by a type:} 202 | typed_vars : VAR_NAME+ '-' var_type; 203 | typed_var : VAR_NAME '-' var_type; 204 | typed_objs : new_consts+ '-' var_type; 205 | new_consts : NAME; 206 | var_type : NAME | '(' 'either' var_type+ ')'; 207 | 208 | // @LABEL {"require"-statements start with a ":"-symbol:} 209 | REQUIRE_NAME : ':' NAME; 210 | 211 | // @LABEL {Names of variables start with a "?":} 212 | var_or_const : NAME | VAR_NAME; 213 | VAR_NAME : '?'NAME; 214 | 215 | // @LABEL {Basic name definition:} 216 | term : NAME | VAR_NAME | functionterm; 217 | functionterm : '(' func_symbol term* ')'; 218 | func_symbol : NAME; 219 | NAME : [a-zA-Z][a-zA-Z0-9\-_]* ; 220 | COMMENT : (';' ~[\r\n]* ('\r'|'\n') ('\r'|'\n')? ) -> skip ; 221 | WS : [ \t\r\n]+ -> skip ; 222 | NUMBER : [0-9][0-9]* '.'? [0-9]* | '.' [0-9]*; 223 | 224 | // 225 | /*********************************************************************************/ 226 | // 227 | // Problem Definition 228 | // 229 | 230 | problem : '(' 'define' '(' 'problem' NAME ')' 231 | '(' ':domain' NAME ')' 232 | require_def? 233 | p_object_declaration? 234 | p_htn? 235 | p_init 236 | p_goal? 237 | ')'; 238 | 239 | p_object_declaration : '(' ':objects' typed_obj_list')'; 240 | p_init : '(' ':init' init_el*')'; 241 | init_el : literal | num_init; 242 | num_init : equallity f_head NUMBER ')'; 243 | p_goal : '(' ':goal' gd ')'; 244 | 245 | p_htn : '(' ':htn' 246 | (':parameters' '(' typed_var_list ')')? 247 | tasknetwork_def; 248 | -------------------------------------------------------------------------------- /doc/antlrHDDL.g4: -------------------------------------------------------------------------------- 1 | grammar antlrHDDL; 2 | 3 | /** 4 | * Created by Daniel Höller, Ulm University (daniel.hoeller@uni-ulm.de) 5 | * and Mario Schmautz, Ulm University (mario.schmautz@uni-ulm.de) [some refactoring & additions] 6 | * 7 | * - This file contains the grammar for the ANTLR parser generator 8 | * - It describes an extension of the Planning Domain Definition Language to describe hierarchical 9 | * planning problems like Hybrid Planning or Hierarchical Task Network planning. 10 | * - It is based on the PDDL 2.1 definition by Maria Fox & Derek Long (so far, only the non-temporal part) 11 | **/ 12 | 13 | // @IGNORE 14 | hddl_file : domain | problem; 15 | 16 | // 17 | // General Structure of a Domain Definition 18 | // 19 | // @MODIFIED 20 | // @LABEL {The domain definition has been extended by definitions for compound tasks and methods.} 21 | domain : '(' 'define' '(' 'domain' domain_symbol ')' 22 | require_def? 23 | type_def? 24 | const_def? 25 | predicates_def? 26 | funtions_def? 27 | comp_task_def* // @HIGHLIGHT 28 | method_def* // @HIGHLIGHT 29 | action_def* ')'; 30 | 31 | // @PDDL 32 | domain_symbol : NAME; 33 | 34 | // 35 | // Requirement Statement 36 | // 37 | // @PDDL 38 | require_def : '(' ':requirements' require_defs ')'; 39 | require_defs : REQUIRE_NAME+; 40 | 41 | // 42 | // Type Definition 43 | // 44 | // @PDDL 45 | type_def : '(' ':types' type_def_list ')'; 46 | type_def_list : NAME* | (new_types '-' var_type type_def_list) ; 47 | new_types : NAME+; 48 | 49 | // 50 | // Domain Constant Definition 51 | // 52 | // @PDDL 53 | const_def : '(' ':constants' typed_obj_list ')'; 54 | 55 | // 56 | // Predicate Definition 57 | // 58 | // @PDDL 59 | predicates_def : '(' ':predicates' atomic_formula_skeleton+ ')'; 60 | atomic_formula_skeleton : '(' predicate typed_var_list ')'; 61 | 62 | // 63 | // Function Definition 64 | // 65 | // @PDDL 66 | funtions_def : '(' ':functions' ( atomic_formula_skeleton ('-' 'number' | var_type )?)+')'; 67 | 68 | // 69 | // Task Definition 70 | // 71 | // @HDDL 72 | // @LABEL {Abstract tasks are defined similar to actions. To use preconditions and effects in the definition, 73 | // please add the requirement definition :htn-abstract-actions} 74 | comp_task_def : 75 | '(' ':task' task_def; 76 | 77 | task_def : task_symbol 78 | ':parameters' '(' typed_var_list ')' 79 | (':precondition' gd)? 80 | (':effect' effect)? ')'; 81 | 82 | task_symbol : NAME; 83 | 84 | // 85 | // Method Definition 86 | // 87 | // @HDDL 88 | // @LABEL {In a pure HTN setting, methods consist of the definition of the abstract task they may decompose as well as the 89 | // resulting task network. The parameters of a method are supposed to include all parameters of the abstract task 90 | // that it decomposes as well as those of the tasks in its network of subtasks. By setting the :htn-method-pre-eff 91 | // requirement, one might use method preconditions and effects similar to the ones used in SHOP.} 92 | method_def : 93 | '(' ':method' method_symbol 94 | ':parameters' '(' typed_var_list ')' 95 | ':task' '(' task_symbol var_or_const* ')' 96 | (':precondition' gd)? 97 | (':effect' effect)? 98 | tasknetwork_def; 99 | 100 | // 101 | // Task Definition 102 | // 103 | // @HDDL 104 | // @LABEL {The following definition of a task network is used in method definitions as well as in the problem definition 105 | // to define the intial task network. It contains the definition of a number of tasks as well sets of ordering 106 | // constraints, variable constraints between any method parameters. Please use the requirement :htn-causal-links 107 | // to include causal links into the model. When the keys :ordered-subtasks or :ordered-tasks are used, the 108 | // network is regarded to be totally ordered. In the other cases, ordering relations may be defined in the 109 | // respective section. To do so, the task definition includes an id for every task that can be referenced here. 110 | // They are also used to define causal links. Two dedicated ids "init" and "goal" can be used in causal link 111 | // definition to reference the initial state and the goal definition.} 112 | tasknetwork_def : 113 | ((':subtasks' | ':tasks' | ':ordered-subtasks' | ':ordered-tasks') subtask_defs)? 114 | ((':ordering' | ':order') ordering_defs)? 115 | (':constraints' constraint_defs)? 116 | ((':causal-links' | ':causallinks') causallink_defs)? 117 | ')'; 118 | 119 | method_symbol : NAME; 120 | 121 | // 122 | // Subtasks 123 | // 124 | // @HDDL 125 | // @LABEL {The subtask definition may contain one or more subtasks. The tasks consist of a task symbol as well as a 126 | // list of parameters. In case of a method's subnetwork, these parameters have to be included in the method's 127 | // parameters, in case of the initial task network, they have to be defined as constants in s0 or in a dedicated 128 | // parameter list (see definition of the initial task network). The tasks may start with an id that can 129 | // be used to define ordering constraints and causal links.} 130 | subtask_defs : '(' ')' | subtask_def | '(' 'and' subtask_def+ ')'; 131 | subtask_def : ('(' task_symbol var_or_const* ')' | '(' subtask_id '(' task_symbol var_or_const* ')' ')'); 132 | subtask_id : NAME; 133 | 134 | // 135 | // Ordering 136 | // 137 | // @HDDL 138 | // @LABEL {The ordering constraints are defined via the task ids. They have to induce a partial order.} 139 | ordering_defs : '(' ')' | ordering_def | '(' 'and' ordering_def+ ')'; 140 | ordering_def : '(' subtask_id '<' subtask_id ')'; 141 | 142 | // 143 | // Variable Constraits 144 | // 145 | // @HDDL 146 | // @LABEL {The variable constraints enable to codesignate or non-codesignate variables; or to enforce (or forbid) a 147 | // variable to have a certain type.} 148 | // @EXAMPLE {(= ?v1 ?v2)), (not (= ?v3 ?v4)), (sort ?v - type), (not (sort ?v - type))} 149 | constraint_defs : '(' ')' | constraint_def | '(' 'and' constraint_def+ ')'; 150 | constraint_def : '(' ')' | '(' 'not' equallity var_or_const var_or_const')' ')' | equallity var_or_const var_or_const ')' 151 | | '(' ('type' | 'typeof' | 'sort' | 'sortof') typed_var ')' 152 | | '(' 'not' '(' ('type' | 'typeof' | 'sort' | 'sortof') typed_var ')' ')' ; 153 | 154 | // 155 | // Causal Links 156 | // 157 | // @HDDL 158 | // @LABEL {Causal links in the model enable the predefinition on which action supports a certain precondition. They 159 | // reference the tasks by the ids that are also used in the definition of ordering constraints.} 160 | causallink_defs : '(' ')' | causallink_def | '(' 'and' causallink_def+ ')'; 161 | causallink_def : '(' subtask_id literal subtask_id ')'; 162 | 163 | // 164 | // Action Definition 165 | // 166 | // @MODIFIED 167 | // @LABEL {The original action definition of PDDL has been split up to reuse its body in the task definition.} 168 | action_def : 169 | '(' ':action' task_def; 170 | 171 | // 172 | // Goal Description 173 | // @LABEL {gd means "goal description". It is used to define goals and preconditions. The PDDL 2.1 definition has been extended by the LTL defintions given by Gerevini andLon "Plan Constraints and Preferences in PDDL3"} 174 | // 175 | // @MODIFIED 176 | gd : gd_empty | atomic_formula | gd_negation | gd_implication | gd_conjuction | gd_disjuction | gd_existential | gd_universal | gd_equality_constraint 177 | | gd_ltl_at_end | gd_ltl_always | gd_ltl_sometime | gd_ltl_at_most_once | gd_ltl_sometime_after | gd_ltl_sometime_before 178 | | gd_preference; 179 | 180 | gd_empty : '(' ')'; 181 | gd_conjuction : '(' 'and' gd+ ')'; 182 | gd_disjuction : '(' 'or' gd+ ')'; 183 | gd_negation : '(' 'not' gd ')'; 184 | gd_implication : '(' 'imply' gd gd ')'; // new 185 | gd_existential : '(' 'exists' '(' typed_var_list ')' gd ')'; 186 | gd_universal : '(' 'forall' '(' typed_var_list ')' gd ')'; 187 | 188 | gd_equality_constraint : equallity var_or_const var_or_const ')'; 189 | 190 | gd_ltl_at_end : '(' 'at end' gd ')'; 191 | gd_ltl_always : '(' 'always' gd ')'; 192 | gd_ltl_sometime : '(' 'sometime' gd ')'; 193 | gd_ltl_at_most_once : '(' 'at-most-once' gd ')'; 194 | gd_ltl_sometime_after : '(' 'sometime-after' gd gd ')'; 195 | gd_ltl_sometime_before : '(' 'sometime-before' gd gd ')'; 196 | 197 | gd_preference : '(' 'preference' NAME gd ')'; 198 | 199 | 200 | // 201 | // Effects 202 | // 203 | // @LABEL {In contrast to earlier versions of this grammar, nested conditional effects are now permitted. 204 | // This is not allowed in PDDL 2.1} 205 | effect : eff_empty | eff_conjunction | eff_universal | eff_conditional | literal | p_effect; 206 | 207 | eff_empty : '(' ')'; 208 | eff_conjunction : '(' 'and' effect+ ')'; 209 | eff_universal : '(' 'forall' '(' typed_var_list ')' effect ')'; 210 | eff_conditional : '(' 'when' gd effect ')'; 211 | 212 | literal : neg_atomic_formula | atomic_formula; 213 | neg_atomic_formula : '(' 'not' atomic_formula ')'; 214 | 215 | p_effect : '(' assign_op f_head f_exp ')'; 216 | 217 | assign_op : 'assign' | 'scale-down' | 'scale-up' | 'increase' | 'decrease'; 218 | 219 | f_head : func_symbol | '(' func_symbol term* ')'; 220 | 221 | f_exp : NUMBER | '(' bin_op f_exp f_exp ')' | '(' multi_op f_exp f_exp+ ')' | '(' '-' f_exp ')' | f_head; 222 | 223 | bin_op : multi_op | '-' | '/'; 224 | 225 | multi_op : '+' | '*'; 226 | 227 | // 228 | // Basic Definitions 229 | // 230 | 231 | // @LABEL {Predicate and atom definition:} 232 | atomic_formula : '('predicate var_or_const*')'; 233 | predicate : NAME; 234 | 235 | // @LABEL {Special "predicate" for equallity:} 236 | equallity : '(' '=' | '(='; 237 | 238 | // @LABEL {Lists of typed variables and objects:} 239 | typed_var_list : typed_vars*; 240 | typed_obj_list : typed_objs*; 241 | 242 | // @LABEL {One or more variable names, followed by a type:} 243 | typed_vars : VAR_NAME+ '-' var_type; 244 | typed_var : VAR_NAME '-' var_type; 245 | typed_objs : new_consts+ '-' var_type; 246 | new_consts : NAME; 247 | var_type : NAME | '(' 'either' var_type+ ')'; 248 | 249 | // @LABEL {"require"-statements start with a ":"-symbol:} 250 | REQUIRE_NAME : ':' NAME; 251 | 252 | // @LABEL {Names of variables start with a "?":} 253 | var_or_const : NAME | VAR_NAME; 254 | VAR_NAME : '?'NAME; 255 | 256 | // @LABEL {Basic name definition:} 257 | term : NAME | VAR_NAME | functionterm; 258 | functionterm : '(' func_symbol term* ')'; 259 | func_symbol : NAME; 260 | NAME : [a-zA-Z][a-zA-Z0-9\-_]* ; 261 | COMMENT : (';' ~[\r\n]* ('\r'|'\n') ('\r'|'\n')? ) -> skip ; 262 | WS : [ \t\r\n]+ -> skip ; 263 | NUMBER : [0-9][0-9]* '.'? [0-9]* | '.' [0-9]*; 264 | 265 | // 266 | /*********************************************************************************/ 267 | // 268 | // Problem Definition 269 | // 270 | 271 | problem : '(' 'define' '(' 'problem' NAME ')' 272 | '(' ':domain' NAME ')' 273 | require_def? 274 | p_object_declaration? 275 | p_htn? 276 | p_init 277 | p_goal? 278 | p_constraint? 279 | metric_spec? 280 | ')'; 281 | 282 | p_object_declaration : '(' ':objects' typed_obj_list')'; 283 | p_init : '(' ':init' init_el*')'; 284 | init_el : literal | num_init; 285 | num_init : equallity f_head NUMBER ')'; 286 | p_goal : '(' ':goal' gd ')'; 287 | 288 | p_htn : '(' (':htn'|':htnti') 289 | (':parameters' '(' typed_var_list ')')? 290 | tasknetwork_def; 291 | 292 | metric_spec : '(' ':metric' optimization ground_f_exp')'; 293 | optimization : 'minimize' | 'maximize'; 294 | ground_f_exp : '(' bin_op ground_f_exp ground_f_exp ')' 295 | | '(' multi_op ground_f_exp ground_f_exp+ ')' 296 | | ('(' '-' | '(-') ground_f_exp ')' 297 | | NUMBER 298 | | '(' func_symbol NAME* ')' 299 | | 'total-time' 300 | | func_symbol; 301 | 302 | p_constraint : '(' ':constraints' gd ')'; 303 | -------------------------------------------------------------------------------- /doc/hddl-cleaned.y: -------------------------------------------------------------------------------- 1 | %{ 2 | // Declare stuff from Flex that Bison needs to know about: 3 | extern int yylex(); 4 | extern int yyparse(); 5 | extern FILE *yyin; 6 | 7 | void yyerror(const char *s); 8 | %} 9 | 10 | %locations 11 | 12 | %token KEY_TYPES KEY_DEFINE KEY_DOMAIN KEY_PROBLEM KEY_REQUIREMENTS KEY_PREDICATES 13 | %token KEY_TASK KEY_CONSTANTS KEY_ACTION KEY_PARAMETERS KEY_PRECONDITION KEY_EFFECT KEY_METHOD 14 | %token KEY_GOAL KEY_INIT KEY_OBJECTS KEY_HTN 15 | %token KEY_AND KEY_OR KEY_NOT KEY_IMPLY KEY_FORALL KEY_EXISTS KEY_WHEN KEY_INCREASE KEY_TYPEOF 16 | %token KEY_CONSTRAINTS KEY_ORDER KEY_ORDER_TASKS KEY_TASKS 17 | %token NAME REQUIRE_NAME VAR_NAME 18 | %token INT 19 | 20 | 21 | %% 22 | document: domain | problem 23 | 24 | 25 | domain: '(' KEY_DEFINE '(' KEY_DOMAIN domain_symbol ')' 26 | domain_defs 27 | ')' 28 | domain_defs: domain_defs require_def | 29 | domain_defs type_def | 30 | domain_defs const_def | 31 | domain_defs predicates_def | 32 | domain_defs task_def | 33 | domain_defs method_def | 34 | 35 | problem: '(' KEY_DEFINE '(' KEY_PROBLEM NAME ')' 36 | '(' KEY_DOMAIN NAME ')' 37 | problem_defs 38 | ')' 39 | 40 | problem_defs: problem_defs require_def | 41 | problem_defs p_object_declaration | 42 | problem_defs p_htn | 43 | problem_defs p_init | 44 | problem_defs p_goal | 45 | problem_defs p_constraint | 46 | 47 | p_object_declaration : '(' KEY_OBJECTS constant_declaration_list')'; 48 | p_init : '(' KEY_INIT init_el ')'; 49 | init_el : init_el literal | 50 | p_goal : '(' KEY_GOAL gd ')' 51 | 52 | htn_type: KEY_HTN | KEY_TIHTN 53 | parameters-option: KEY_PARAMETERS '(' typed_var_list ')' | 54 | p_htn : '(' htn_type 55 | parameters-option 56 | tasknetwork_def 57 | ')' 58 | 59 | p_constraint : '(' KEY_CONSTRAINTS gd ')' 60 | 61 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 62 | // @PDDL 63 | domain_symbol : NAME 64 | 65 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 66 | // Requirement Statement 67 | // @PDDL 68 | require_def : '(' KEY_REQUIREMENTS require_defs ')' 69 | require_defs : require_defs REQUIRE_NAME | 70 | 71 | 72 | 73 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 74 | // Type Definition 75 | // @PDDL 76 | type_def : '(' KEY_TYPES type_def_list ')'; 77 | type_def_list : NAME-list 78 | | NAME-list-non-empty '-' NAME type_def_list 79 | 80 | 81 | 82 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 83 | // Constant Definition 84 | const_def : '(' KEY_CONSTANTS constant_declaration_list ')' 85 | // this is used in both the domain and the initial state 86 | constant_declaration_list : constant_declaration_list constant_declarations | 87 | constant_declarations : NAME-list-non-empty '-' NAME 88 | 89 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 90 | // Predicate Definition 91 | // @PDDL 92 | predicates_def : '(' KEY_PREDICATES atomic_predicate_def-list ')' 93 | 94 | atomic_predicate_def-list : atomic_predicate_def-list atomic_predicate_def | 95 | atomic_predicate_def : '(' NAME typed_var_list ')' 96 | 97 | 98 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 99 | // Task Definition 100 | // @HDDL 101 | // @LABEL Abstract tasks are defined similar to actions. To use preconditions and effects in the definition, 102 | // please add the requirement definition :htn-abstract-actions 103 | // @NOTE tasks, i.e. abstract tasks, will not have preconditions and effects. This rule is just for ease of parsing 104 | 105 | task_or_action: KEY_TASK | KEY_ACTION 106 | 107 | task_def : '(' task_or_action NAME 108 | KEY_PARAMETERS '(' typed_var_list ')' 109 | precondition_option 110 | effect_option ')' 111 | 112 | precondition_option: KEY_PRECONDITION gd | 113 | effect_option: KEY_EFFECT effect | 114 | 115 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 116 | // Method Definition 117 | // @HDDL 118 | // @LABEL In a pure HTN setting, methods consist of the definition of the abstract task they may decompose as well as the 119 | // resulting task network. The parameters of a method are supposed to include all parameters of the abstract task 120 | // that it decomposes as well as those of the tasks in its network of subtasks. By setting the :htn-method-pre-eff 121 | // requirement, one might use method preconditions and effects similar to the ones used in SHOP. 122 | method_def : 123 | '(' KEY_METHOD NAME 124 | KEY_PARAMETERS '(' typed_var_list ')' 125 | KEY_TASK '(' NAME var_or_const-list ')' 126 | precondition_option 127 | tasknetwork_def 128 | ')' 129 | 130 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 131 | // Task Definition 132 | // @HDDL 133 | // @LABEL The following definition of a task network is used in method definitions as well as in the problem definition 134 | // to define the intial task network. It contains the definition of a number of tasks as well sets of ordering 135 | // constraints, variable constraints between any method parameters. Please use the requirement :htn-causal-links 136 | // to include causal links into the model. When the keys :ordered-subtasks or :ordered-tasks are used, the 137 | // network is regarded to be totally ordered. In the other cases, ordering relations may be defined in the 138 | // respective section. To do so, the task definition includes an id for every task that can be referenced here. 139 | // They are also used to define causal links. Two dedicated ids "init" and "goal" can be used in causal link 140 | // definition to reference the initial state and the goal definition. 141 | tasknetwork_def : 142 | subtasks_option 143 | ordering_option 144 | constraints_option 145 | 146 | subtasks_option: KEY_TASKS subtask_defs 147 | | KEY_ORDER_TASKS subtask_defs 148 | | 149 | 150 | ordering_option: KEY_ORDER ordering_defs | 151 | constraints_option: KEY_CONSTRAINTS constraint_def | 152 | 153 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 154 | // Subtasks 155 | // @HDDL 156 | // @LABEL The subtask definition may contain one or more subtasks. The tasks consist of a task symbol as well as a 157 | // list of parameters. In case of a method's subnetwork, these parameters have to be included in the method's 158 | // parameters, in case of the initial task network, they have to be defined as constants in s0 or in a dedicated 159 | // parameter list (see definition of the initial task network). The tasks may start with an id that can 160 | // be used to define ordering constraints and causal links. 161 | subtask_defs : '(' ')' 162 | | subtask_def 163 | | '(' KEY_AND subtask_def-list ')' 164 | subtask_def-list : subtask_def-list subtask_def 165 | | 166 | subtask_def : '(' NAME var_or_const-list ')' 167 | | '(' NAME '(' NAME var_or_const-list ')' ')' 168 | 169 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 170 | // 171 | // Ordering 172 | // 173 | // @HDDL 174 | // @LABEL The ordering constraints are defined via the task ids. They have to induce a partial order. 175 | ordering_defs : '(' ')' 176 | | ordering_def 177 | | '(' KEY_AND ordering_def-list ')' 178 | ordering_def-list: ordering_def-list ordering_def 179 | | 180 | ordering_def : '(' NAME '<' NAME ')' 181 | 182 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 183 | // Variable Constraits 184 | // @HDDL 185 | // @LABEL The variable constraints enable to codesignate or non-codesignate variables, or to enforce (or forbid) a 186 | // variable to have a certain type. 187 | // @EXAMPLE (= ?v1 ?v2)), (not (= ?v3 ?v4)), (sort ?v - type), (not (sort ?v - type)) 188 | constraint_def-list: constraint_def-list constraint_def 189 | | 190 | constraint_def : '(' ')' 191 | | '(' KEY_AND constraint_def-list ')' 192 | | '(' '=' var_or_const var_or_const ')' 193 | | '(' KEY_NOT '(' '=' var_or_const var_or_const ')' ')' 194 | 195 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 196 | // Goal Description 197 | // @LABEL gd means "goal description". It is used to define goals and preconditions. The PDDL 2.1 definition has been extended by the LTL defintions given by Gerevini andLon "Plan Constraints and Preferences in PDDL3" 198 | gd : gd_empty 199 | | atomic_formula 200 | | gd_negation 201 | | gd_implication 202 | | gd_conjuction 203 | | gd_disjuction 204 | | gd_existential 205 | | gd_universal 206 | | gd_equality_constraint 207 | 208 | gd-list : gd-list gd 209 | | 210 | 211 | gd_empty : '(' ')' 212 | gd_conjuction : '(' KEY_AND gd-list ')' 213 | gd_disjuction : '(' KEY_OR gd-list ')' 214 | gd_negation : '(' KEY_NOT gd ')' 215 | gd_implication : '(' KEY_IMPLY gd gd ')' 216 | gd_existential : '(' KEY_EXISTS '(' typed_var_list ')' gd ')' 217 | gd_universal : '(' KEY_FORALL '(' typed_var_list ')' gd ')' 218 | gd_equality_constraint : '(' '=' var_or_const var_or_const ')' 219 | 220 | var_or_const-list : var_or_const-list NAME 221 | | var_or_const-list VAR_NAME 222 | | 223 | 224 | var_or_const : NAME | VAR_NAME 225 | atomic_formula : '('NAME var_or_const-list')' 226 | 227 | 228 | 229 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 230 | // Effects 231 | // @LABEL In contrast to earlier versions of this grammar, nested conditional effects are now permitted. 232 | // This is not allowed in PDDL 2.1 233 | 234 | effect-list: effect-list effect 235 | | 236 | 237 | effect : eff_empty 238 | | eff_conjunction 239 | | eff_universal 240 | | eff_conditional 241 | | literal 242 | 243 | eff_empty : '(' ')' 244 | eff_conjunction : '(' KEY_AND effect-list ')' 245 | eff_universal : '(' KEY_FORALL '(' typed_var_list ')' effect ')' 246 | eff_conditional : '(' KEY_WHEN gd effect ')' 247 | 248 | 249 | literal : neg_atomic_formula | atomic_formula 250 | neg_atomic_formula : '(' KEY_NOT atomic_formula ')' 251 | 252 | 253 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 254 | // elementary list of names 255 | NAME-list-non-empty: NAME-list NAME 256 | NAME-list: NAME-list NAME 257 | | 258 | 259 | 260 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 261 | // elementary list of variable names 262 | VAR_NAME-list-non-empty: VAR_NAME-list VAR_NAME 263 | VAR_NAME-list: VAR_NAME-list VAR_NAME 264 | | 265 | 266 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 267 | // lists of variables 268 | typed_vars : VAR_NAME-list-non-empty '-' NAME 269 | typed_var : VAR_NAME '-' NAME 270 | typed_var_list : typed_var_list typed_vars 271 | | 272 | 273 | %% 274 | void run_parser_on_file(FILE* f){ 275 | yyin = f; 276 | yyparse(); 277 | } 278 | 279 | void yyerror(const char *s) { 280 | cout << "Parse error in line " << yylloc.first_line << endl << "Message: " << s << endl; 281 | // might as well halt now: 282 | exit(-1); 283 | } 284 | -------------------------------------------------------------------------------- /doc/hddl-token-cleaned.l: -------------------------------------------------------------------------------- 1 | %{ 2 | // import header file generated for from the bison file s.t. KEYs are known here 3 | #include "hddl.hpp" 4 | %} 5 | %option noyywrap 6 | %option yylineno 7 | %% 8 | \( {return '('; } 9 | \) {return ')'; } 10 | - {return '-'; } 11 | = {return '='; } 12 | \< {return '<'; } 13 | define {return KEY_DEFINE;} 14 | domain {return KEY_DOMAIN;} 15 | :domain {return KEY_DOMAIN;} 16 | problem {return KEY_PROBLEM;} 17 | :requirements {return KEY_REQUIREMENTS;} 18 | :types {return KEY_TYPES;} 19 | :constants {return KEY_CONSTANTS;} 20 | :predicates {return KEY_PREDICATES;} 21 | :task {return KEY_TASK;} 22 | :action {return KEY_ACTION;} 23 | :parameters {return KEY_PARAMETERS;} 24 | :precondition {return KEY_PRECONDITION;} 25 | :effect {return KEY_EFFECT;} 26 | :method {return KEY_METHOD;} 27 | :init {return KEY_INIT;} 28 | :goal {return KEY_GOAL;} 29 | :htn {return KEY_HTN;} 30 | :objects {return KEY_OBJECTS;} 31 | 32 | :subtasks {return KEY_TASKS;} 33 | :tasks {return KEY_TASKS;} 34 | :ordered-subtasks {return KEY_ORDER_TASKS;} 35 | :ordered-tasks {return KEY_ORDER_TASKS;} 36 | :ordering {return KEY_ORDER;} 37 | :order {return KEY_ORDER;} 38 | 39 | :constraints {return KEY_CONSTRAINTS;} 40 | 41 | and {return KEY_AND;} 42 | or {return KEY_OR;} 43 | not {return KEY_NOT;} 44 | imply {return KEY_IMPLY;} 45 | forall {return KEY_FORALL;} 46 | exists {return KEY_EXISTS;} 47 | when {return KEY_WHEN;} 48 | 49 | type {return KEY_TYPEOF;} 50 | typeof {return KEY_TYPEOF;} 51 | sort {return KEY_TYPEOF;} 52 | sortof {return KEY_TYPEOF;} 53 | 54 | 55 | [ \t\n\r] ; // whitespace 56 | ;.*[\n\r] ; // comments 57 | \?[a-zA-Z][a-zA-Z0-9\-_]* {yylval.sval = strdup(yytext); return VAR_NAME;} 58 | :[a-zA-Z][a-zA-Z0-9\-_]* {yylval.sval = strdup(yytext); return REQUIRE_NAME;} 59 | [a-zA-Z][a-zA-Z0-9\-_]* {yylval.sval = strdup(yytext); return NAME;} 60 | [0-9]+ {yylval.fval = atoi(yytext); return INT;} 61 | %% 62 | -------------------------------------------------------------------------------- /doc/hddl-token.l: -------------------------------------------------------------------------------- 1 | %{ 2 | // import header file generated for from the bison file s.t. KEYs are known here 3 | #include "hddl.hpp" 4 | %} 5 | %option noyywrap 6 | %option yylineno 7 | %% 8 | \( {return '('; } 9 | \) {return ')'; } 10 | - {return '-'; } 11 | = {return '='; } 12 | \< {return '<'; } 13 | define {return KEY_DEFINE;} 14 | domain {return KEY_DOMAIN;} 15 | :domain {return KEY_DOMAIN;} 16 | problem {return KEY_PROBLEM;} 17 | :requirements {return KEY_REQUIREMENTS;} 18 | :types {return KEY_TYPES;} 19 | :constants {return KEY_CONSTANTS;} 20 | :predicates {return KEY_PREDICATES;} 21 | :task {return KEY_TASK;} 22 | :action {return KEY_ACTION;} 23 | :parameters {return KEY_PARAMETERS;} 24 | :precondition {return KEY_PRECONDITION;} 25 | :effect {return KEY_EFFECT;} 26 | :method {return KEY_METHOD;} 27 | :init {return KEY_INIT;} 28 | :goal {return KEY_GOAL;} 29 | :htn {return KEY_HTN;} 30 | :tihtn {return KEY_TIHTN;} 31 | :htnti {return KEY_TIHTN;} 32 | :objects {return KEY_OBJECTS;} 33 | 34 | :subtasks {return KEY_TASKS;} 35 | :tasks {return KEY_TASKS;} 36 | :ordered-subtasks {return KEY_ORDER_TASKS;} 37 | :ordered-tasks {return KEY_ORDER_TASKS;} 38 | :ordering {return KEY_ORDER;} 39 | :order {return KEY_ORDER;} 40 | 41 | :constraints {return KEY_CONSTRAINTS;} 42 | 43 | :causal-links {return KEY_CAUSAL_LINKS;} 44 | :causallinks {return KEY_CAUSAL_LINKS;} 45 | 46 | and {return KEY_AND;} 47 | or {return KEY_OR;} 48 | not {return KEY_NOT;} 49 | imply {return KEY_IMPLY;} 50 | forall {return KEY_FORALL;} 51 | exists {return KEY_EXISTS;} 52 | when {return KEY_WHEN;} 53 | increase {return KEY_INCREASE;} 54 | 55 | type {return KEY_TYPEOF;} 56 | typeof {return KEY_TYPEOF;} 57 | sort {return KEY_TYPEOF;} 58 | sortof {return KEY_TYPEOF;} 59 | 60 | 61 | [ \t\n\r] ; // whitespace 62 | ;.*[\n\r] ; // comments 63 | \?[a-zA-Z][a-zA-Z0-9\-_]* {yylval.sval = strdup(yytext); return VAR_NAME;} 64 | :[a-zA-Z][a-zA-Z0-9\-_]* {yylval.sval = strdup(yytext); return REQUIRE_NAME;} 65 | [a-zA-Z][a-zA-Z0-9\-_]* {yylval.sval = strdup(yytext); return NAME;} 66 | [0-9]+\.[0-9]+ {yylval.fval = atof(yytext); return FLOAT;} 67 | [0-9]+ {yylval.fval = atoi(yytext); return INT;} 68 | %% 69 | -------------------------------------------------------------------------------- /doc/hddl.y: -------------------------------------------------------------------------------- 1 | %{ 2 | // Declare stuff from Flex that Bison needs to know about: 3 | extern int yylex(); 4 | extern int yyparse(); 5 | extern FILE *yyin; 6 | 7 | void yyerror(const char *s); 8 | %} 9 | 10 | %locations 11 | 12 | %token KEY_TYPES KEY_DEFINE KEY_DOMAIN KEY_PROBLEM KEY_REQUIREMENTS KEY_PREDICATES 13 | %token KEY_TASK KEY_CONSTANTS KEY_ACTION KEY_PARAMETERS KEY_PRECONDITION KEY_EFFECT KEY_METHOD 14 | %token KEY_GOAL KEY_INIT KEY_OBJECTS KEY_HTN KEY_TIHTN 15 | %token KEY_AND KEY_OR KEY_NOT KEY_IMPLY KEY_FORALL KEY_EXISTS KEY_WHEN KEY_INCREASE KEY_TYPEOF 16 | %token KEY_CAUSAL_LINKS KEY_CONSTRAINTS KEY_ORDER KEY_ORDER_TASKS KEY_TASKS 17 | %token NAME REQUIRE_NAME VAR_NAME 18 | %token FLOAT 19 | %token INT 20 | 21 | 22 | %% 23 | document: domain | problem 24 | 25 | 26 | domain: '(' KEY_DEFINE '(' KEY_DOMAIN domain_symbol ')' 27 | domain_defs 28 | ')' 29 | domain_defs: domain_defs require_def | 30 | domain_defs type_def | 31 | domain_defs const_def | 32 | domain_defs predicates_def | 33 | domain_defs task_def | 34 | domain_defs method_def | 35 | 36 | problem: '(' KEY_DEFINE '(' KEY_PROBLEM NAME ')' 37 | '(' KEY_DOMAIN NAME ')' 38 | problem_defs 39 | ')' 40 | 41 | problem_defs: problem_defs require_def | 42 | problem_defs p_object_declaration | 43 | problem_defs p_htn | 44 | problem_defs p_init | 45 | problem_defs p_goal | 46 | problem_defs p_constraint | 47 | 48 | p_object_declaration : '(' KEY_OBJECTS constant_declaration_list')'; 49 | p_init : '(' KEY_INIT init_el ')'; 50 | init_el : init_el literal | 51 | p_goal : '(' KEY_GOAL gd ')' 52 | 53 | htn_type: KEY_HTN | KEY_TIHTN 54 | parameters-option: KEY_PARAMETERS '(' typed_var_list ')' | 55 | p_htn : '(' htn_type 56 | parameters-option 57 | tasknetwork_def 58 | ')' 59 | 60 | p_constraint : '(' KEY_CONSTRAINTS gd ')' 61 | 62 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 63 | // @PDDL 64 | domain_symbol : NAME 65 | 66 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 67 | // Requirement Statement 68 | // @PDDL 69 | require_def : '(' KEY_REQUIREMENTS require_defs ')' 70 | require_defs : require_defs REQUIRE_NAME | 71 | 72 | 73 | 74 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 75 | // Type Definition 76 | // @PDDL 77 | type_def : '(' KEY_TYPES type_def_list ')'; 78 | type_def_list : NAME-list 79 | | NAME-list-non-empty '-' NAME type_def_list 80 | 81 | 82 | 83 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 84 | // Constant Definition 85 | const_def : '(' KEY_CONSTANTS constant_declaration_list ')' 86 | // this is used in both the domain and the initial state 87 | constant_declaration_list : constant_declaration_list constant_declarations | 88 | constant_declarations : NAME-list-non-empty '-' NAME 89 | 90 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 91 | // Predicate Definition 92 | // @PDDL 93 | predicates_def : '(' KEY_PREDICATES atomic_predicate_def-list ')' 94 | 95 | atomic_predicate_def-list : atomic_predicate_def-list atomic_predicate_def | 96 | atomic_predicate_def : '(' NAME typed_var_list ')' 97 | 98 | 99 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 100 | // Task Definition 101 | // @HDDL 102 | // @LABEL Abstract tasks are defined similar to actions. To use preconditions and effects in the definition, 103 | // please add the requirement definition :htn-abstract-actions 104 | 105 | task_or_action: KEY_TASK | KEY_ACTION 106 | 107 | task_def : '(' task_or_action NAME 108 | KEY_PARAMETERS '(' typed_var_list ')' 109 | precondition_option 110 | effect_option ')' 111 | 112 | precondition_option: KEY_PRECONDITION gd | 113 | effect_option: KEY_EFFECT effect | 114 | 115 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 116 | // Method Definition 117 | // @HDDL 118 | // @LABEL In a pure HTN setting, methods consist of the definition of the abstract task they may decompose as well as the 119 | // resulting task network. The parameters of a method are supposed to include all parameters of the abstract task 120 | // that it decomposes as well as those of the tasks in its network of subtasks. By setting the :htn-method-pre-eff 121 | // requirement, one might use method preconditions and effects similar to the ones used in SHOP. 122 | method_def : 123 | '(' KEY_METHOD NAME 124 | KEY_PARAMETERS '(' typed_var_list ')' 125 | KEY_TASK '(' NAME var_or_const-list ')' 126 | precondition_option 127 | effect_option 128 | tasknetwork_def 129 | ')' 130 | 131 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 132 | // Task Definition 133 | // @HDDL 134 | // @LABEL The following definition of a task network is used in method definitions as well as in the problem definition 135 | // to define the intial task network. It contains the definition of a number of tasks as well sets of ordering 136 | // constraints, variable constraints between any method parameters. Please use the requirement :htn-causal-links 137 | // to include causal links into the model. When the keys :ordered-subtasks or :ordered-tasks are used, the 138 | // network is regarded to be totally ordered. In the other cases, ordering relations may be defined in the 139 | // respective section. To do so, the task definition includes an id for every task that can be referenced here. 140 | // They are also used to define causal links. Two dedicated ids "init" and "goal" can be used in causal link 141 | // definition to reference the initial state and the goal definition. 142 | tasknetwork_def : 143 | subtasks_option 144 | ordering_option 145 | constraints_option 146 | causal_links_option 147 | 148 | subtasks_option: KEY_TASKS subtask_defs 149 | | KEY_ORDER_TASKS subtask_defs 150 | | 151 | 152 | ordering_option: KEY_ORDER ordering_defs | 153 | constraints_option: KEY_CONSTRAINTS constraint_def | 154 | causal_links_option: KEY_CAUSAL_LINKS causallink_defs | 155 | 156 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 157 | // Subtasks 158 | // @HDDL 159 | // @LABEL The subtask definition may contain one or more subtasks. The tasks consist of a task symbol as well as a 160 | // list of parameters. In case of a method's subnetwork, these parameters have to be included in the method's 161 | // parameters, in case of the initial task network, they have to be defined as constants in s0 or in a dedicated 162 | // parameter list (see definition of the initial task network). The tasks may start with an id that can 163 | // be used to define ordering constraints and causal links. 164 | subtask_defs : '(' ')' 165 | | subtask_def 166 | | '(' KEY_AND subtask_def-list ')' 167 | subtask_def-list : subtask_def-list subtask_def 168 | | 169 | subtask_def : '(' NAME var_or_const-list ')' 170 | | '(' NAME '(' NAME var_or_const-list ')' ')' 171 | 172 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 173 | // 174 | // Ordering 175 | // 176 | // @HDDL 177 | // @LABEL The ordering constraints are defined via the task ids. They have to induce a partial order. 178 | ordering_defs : '(' ')' 179 | | ordering_def 180 | | '(' KEY_AND ordering_def-list ')' 181 | ordering_def-list: ordering_def-list ordering_def 182 | | 183 | ordering_def : '(' NAME '<' NAME ')' 184 | 185 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 186 | // Variable Constraits 187 | // @HDDL 188 | // @LABEL The variable constraints enable to codesignate or non-codesignate variables, or to enforce (or forbid) a 189 | // variable to have a certain type. 190 | // @EXAMPLE (= ?v1 ?v2)), (not (= ?v3 ?v4)), (sort ?v - type), (not (sort ?v - type)) 191 | constraint_def-list: constraint_def-list constraint_def 192 | | 193 | constraint_def : '(' ')' 194 | | '(' KEY_AND constraint_def-list ')' 195 | | '(' '=' var_or_const var_or_const ')' 196 | | '(' KEY_NOT '(' '=' var_or_const var_or_const ')' ')' 197 | | '(' KEY_TYPEOF typed_var ')' 198 | | '(' KEY_NOT '(' KEY_TYPEOF typed_var ')' ')' 199 | 200 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 201 | // Causal Links 202 | // @HDDL 203 | // @LABEL Causal links in the model enable the predefinition on which action supports a certain precondition. They 204 | // reference the tasks by the ids that are also used in the definition of ordering constraints. 205 | causallink_defs : '(' ')' | causallink_def | '(' KEY_AND causallink_def-list ')' 206 | causallink_def-list: causallink_def-list causallink_def | 207 | causallink_def : '(' NAME literal NAME ')' 208 | 209 | 210 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 211 | // Goal Description 212 | // @LABEL gd means "goal description". It is used to define goals and preconditions. The PDDL 2.1 definition has been extended by the LTL defintions given by Gerevini andLon "Plan Constraints and Preferences in PDDL3" 213 | gd : gd_empty 214 | | atomic_formula 215 | | gd_negation 216 | | gd_implication 217 | | gd_conjuction 218 | | gd_disjuction 219 | | gd_existential 220 | | gd_universal 221 | | gd_equality_constraint 222 | 223 | gd-list : gd-list gd 224 | | 225 | 226 | gd_empty : '(' ')' 227 | gd_conjuction : '(' KEY_AND gd-list ')' 228 | gd_disjuction : '(' KEY_OR gd-list ')' 229 | gd_negation : '(' KEY_NOT gd ')' 230 | gd_implication : '(' KEY_IMPLY gd gd ')' 231 | gd_existential : '(' KEY_EXISTS '(' typed_var_list ')' gd ')' 232 | gd_universal : '(' KEY_FORALL '(' typed_var_list ')' gd ')' 233 | gd_equality_constraint : '(' '=' var_or_const var_or_const ')' 234 | 235 | var_or_const-list : var_or_const-list NAME 236 | | var_or_const-list VAR_NAME 237 | | 238 | 239 | var_or_const : NAME | VAR_NAME 240 | atomic_formula : '('NAME var_or_const-list')' 241 | 242 | 243 | 244 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 245 | // Effects 246 | // @LABEL In contrast to earlier versions of this grammar, nested conditional effects are now permitted. 247 | // This is not allowed in PDDL 2.1 248 | 249 | effect-list: effect-list effect 250 | | 251 | 252 | effect : eff_empty 253 | | eff_conjunction 254 | | eff_universal 255 | | eff_conditional 256 | | literal 257 | | p_effect 258 | 259 | eff_empty : '(' ')' 260 | eff_conjunction : '(' KEY_AND effect-list ')' 261 | eff_universal : '(' KEY_FORALL '(' typed_var_list ')' effect ')' 262 | eff_conditional : '(' KEY_WHEN gd effect ')' 263 | 264 | 265 | literal : neg_atomic_formula | atomic_formula 266 | neg_atomic_formula : '(' KEY_NOT atomic_formula ')' 267 | 268 | 269 | // these rules are just here to be able to parse action consts in the future 270 | p_effect : '(' assign_op f_head f_exp ')' // TODO actions costs 271 | assign_op : KEY_INCREASE 272 | f_head : NAME 273 | f_exp : INT 274 | 275 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 276 | // elementary list of names 277 | NAME-list-non-empty: NAME-list NAME 278 | NAME-list: NAME-list NAME 279 | | 280 | 281 | 282 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 283 | // elementary list of variable names 284 | VAR_NAME-list-non-empty: VAR_NAME-list VAR_NAME 285 | VAR_NAME-list: VAR_NAME-list VAR_NAME 286 | | 287 | 288 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 289 | // lists of variables 290 | typed_vars : VAR_NAME-list-non-empty '-' NAME 291 | typed_var : VAR_NAME '-' NAME 292 | typed_var_list : typed_var_list typed_vars 293 | | 294 | 295 | %% 296 | void run_parser_on_file(FILE* f){ 297 | yyin = f; 298 | yyparse(); 299 | } 300 | 301 | void yyerror(const char *s) { 302 | cout << "Parse error in line " << yylloc.first_line << endl << "Message: " << s << endl; 303 | // might as well halt now: 304 | exit(-1); 305 | } 306 | -------------------------------------------------------------------------------- /doc/parser-output-format.md: -------------------------------------------------------------------------------- 1 | --- 2 | geometry: "left=1.5cm,right=1.5cm,top=1.5cm,bottom=1.5cm" 3 | --- 4 | 5 | ## pandaPIparser - Description of the output format 6 | 7 | ### General rules 8 | Any line that starts with a # sign is a comment line. 9 | It is to be ignored. 10 | Comments only occur at the beginning of a line, i.e., if the # sign occurs at a position other than the first, it does not indicate a comment. 11 | 12 | There are no linebreaks or empty lines except if mentioned in this description. Listed items are always separated by a single space between them. There leading spaces, but lists might contain trailing spaces. 13 | 14 | All indices are 0-indexed, as are all lists. 15 | 16 | ### Sections 17 | The output is roughly split into 4 sections 18 | 19 | 1. The logic section 20 | 2. The tasks section 21 | 3. The method section 22 | 4. The init/goal section. 23 | 24 | There are no delimiters between these sections. 25 | They simply follow one another without any marker or empty line. 26 | 27 | ### The Logic Section 28 | 29 | The logic section consists of 30 | 31 | 1. One line containing two space-separated non-negative integers ``C S``, where ``C`` is the number of constants and ``S`` is the number of sorts. 32 | 2. C many lines, each containing a string (not containing a space), listing the constants. The i^th^ such line will be the constant numbered i (0-indexed). 33 | 3. S many lines. Each such line declares a sort and provides the full list of constants that are members of this sort. Note that one constant might occur in multiple sorts. Each contains 34 | 1. One string (not containing a space), the sort's name, followed by a space and 35 | 2. The number of constants of this sort, followed by a space and 36 | 3. A space-separated list of non-negative integers all smaller than C, each indicating a constant. 37 | 4. One line containing a space-separated non-negative integer ``P`` -- the number of predicates. 38 | 5. P many lines. Each predicate has a name and a list of arguments. For each argument, the sort of that argument is given. 39 | Each line comprises 40 | 1. One string (not containing a space), the predicate's name, followed by a space and 41 | 2. The number of arguments and 42 | 3. A space-separated list of non-negative integers all smaller than S, each indicating a sort. 43 | 6. One line containing a number of predicate mutexes, ``M`` 44 | 7. ``M`` many lines, each containing a space-separated pair of predicate indices (non-negative integers `< P`). The two prdicates ``a`` and ``b`` must have exactly the same number of arguments and their types must be exactly identical. Then for every ground instances ``a o1 ... on``, the two facts ``a o1 ... on`` and ``b o1 ... on`` are mutex. This is used to mark the complementary predicates that result from compiling negative preconditions away. 45 | 8. One line containing a space-separated non-negative integer ``F`` -- the number of functions. 46 | 9. F many lines. Each function has a name and a list of arguments. For each argument, the sort of that argument is given. 47 | Each line comprises 48 | 1. One string (not containing a space), the function's name, followed by a space and 49 | 2. A line with a single non-negative integer indicating the number of arguments. 50 | 3. A space-separated list of non-negative integers all smaller than S, each indicating a sort. 51 | 52 | 53 | ### The Task Section 54 | 55 | The task section consists of 56 | 57 | 1. One line containing two space-separated non-negative integers ``A C``, where ``A`` is the number of primitive tasks (or actions) and ``C`` is the number of abstract (or compound) tasks. 58 | 2. Then A many blocks, each describing one action follow. Each action block comprises 59 | 1. One line containing 60 | 1. A string (not containing a space), the action's name 61 | 2. A non-negative number ``OV`` indicating the number of argument variables this action had in the input domain 62 | 3. A non-negative number ``V`` indicating the total number of argument variables of this action. It has to be $OV \leq V$ 63 | 64 | *Note:* The argument variables of this action are numbered 0 to V-1. 65 | The first variables, i.e., 0 to OV-1, are those that originally appeared in the input domain. The additional variables OV to V-1 are variables that have been added by the parser. 66 | 2. One line containing V many integers from 0 to S-1. The i^th^ of these numbers $s_i$ indicates that the variable i is of the sort $s_i$. 67 | 3. One line containing the number of cost statements for this action. 68 | 4. One line for each cost statement. This line contains either 69 | 1. The string ``const`` followed by a space and an integer indicating a cost, or 70 | 2. The string ``var`` followed by a number ``f`` indicating a function, then followed by as many arguments as this function takes. The arguments are indices of argumments of this action. The cost of this action is then the result of the evaluation of the function ``f`` on the given arguments. 71 | 5. One line containing the number of preconditions. 72 | 6. One line for each precondition containing: 73 | 1. An integer ``p`` indicating the predicate of this precondition. 74 | 2. As many integers ``v`` as this predicate takes arguments. These integers refer to the arguments of the action that are to be the arguments of that predicate. I.e. a line ``2 1 5 0`` indicates that the precondition is on predicate No 2, and its arguments are the first, fifth, and zeroth argument of the action. 75 | 7. One line containing the number of unconditional adding effects. 76 | 8. One line for each adding effect, described in the same way as preconditions are. 77 | 9. One line containing the number of conditional adding effects. 78 | 10. One line for each conditional adding effect, containing 79 | 1. A number ``c`` indicating the number of conditions. 80 | 2. Then follow ``c`` many descriptions of preconditions, in the same format as general preconditions all in the same line (attention: you need to extract the number of arguments per predicate to parse this list correctly). 81 | 3. Then follows one description of an adding effect, in the same format as a precondition. 82 | 11. One line containing the number of unconditional deleting effects. 83 | 12. One line for each deleting effect, described in the same way as preconditions are. 84 | 13. One line containing the number of conditional deleing effects. 85 | 14. One line for each conditional deleing effect, describing it in the same way that conditional adding effects are. 86 | 15. One line containing a number ``c``, the number of variable constraints. 87 | 16. One line for each variable constraint, containing 88 | 1. Either the string ``=`` for an equals constraint, or ``!=`` for a not-equals constraint 89 | 2. A number ``v1`` referring to an argument of the action 90 | 3. A number ``v2`` referring to an argument of the action 91 | The implied constraint is that $v_1 = v_2$ or $v_1 \neq v_2$, respectively. 92 | 3. Then follow C many blocks, each descibing an abstract task. Each such block has the same format as an action block, but only contains the sub-elements 1-2. 93 | 94 | 95 | *Note* the primitive and abstract tasks are implicitly numbered by their order in the input file. 96 | The action occuring first has number 0, the second one number 1, and so on. The numbering does _not_ start anew for the abstract tasks. I.e. the first abstract task is always numbered A. 97 | 98 | 99 | ### The Method Section 100 | 101 | The method section consists of 102 | 103 | 1. One line containing a single non-negative integer ``M``. 104 | 2. Then follow ``M`` many blocks, one for each method. Each such block consists of 105 | 1. A single line containing 106 | 1. A string (without spaces) indicating ther name of the method 107 | 2. A number ``t`` with $A \leq t < A+C$ indicating the task that this method decomposes 108 | 3. A number ``v`` indicating the number of variables for this method. The variables are numbered 0 to $v-1$. 109 | 2. One line containing V many integers from 0 to S-1. The i^th^ of these numbers $s_i$ indicates that the variable i is of the sort $s_i$. 110 | 3. One line containing as many integers as the abstract task ``t`` has parameters, each referring to a variable of this method, indicating which variables are those the arguments of the task to be decomposed. 111 | 4. One line with a single non-negative integer ``s`` indicating the number of sub tasks. 112 | 5. Then for each subtask one line describing the subtask containing 113 | 1. An integer ``ts`` indicating the number of the task of this subtask 114 | 2. The method variables that are its arguments. 115 | *Note* The subtasks are implicitly numbered 0 to $s-1$ as given by the order they appear in this list. 116 | 6. One line containing the number of ordering constraints ``o``. 117 | 7. One line containing $2o$ numbers, split into $o$ many pairs (first and second, then third and fourth, and so so). Each such pair ``t1 t2`` indicates that the subtask ``t1`` is to be ordered before ``t2`` 118 | 8. One line for each variable constraint, containing 119 | 1. Either the string ``=`` for an equals constraint, or ``!=`` for a not-equals constraint 120 | 2. A number ``v1`` referring to an argument of the action 121 | 3. A number ``v2`` referring to an argument of the action 122 | The implied constraint is that $v_1 = v_2$ or $v_1 \neq v_2$, respectively. 123 | 124 | ### The Init/Goal Section 125 | 126 | The init and goal section consists of 127 | 128 | 1. One line with two non-negative integers ``I G``, indicating the number of facts true in the initial state ``I`` and the number of goal facts ``G``. 129 | 2. Then follow ``I`` many lines, each describing a fact that is true in the initial state. Each such line contains 130 | 1. A number ``p`` indicating the predicate of the fact. 131 | 2. As many number ``c`` as this predicate takes arguments, each indicating a constant. 132 | 3. Then follow ``G`` many lines, each describing a fact that should be true in the goal, each with the same format as a fact in init. 133 | 4. One line containing a single integer ``T``. If this number is $-1$, this is a classical planning problem. Otherwise, this number is $A \leq T < A+C$ and indicates the initial abstract task of the problem. 134 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CWARN=-Wno-unused-parameter 3 | CERROR= 4 | 5 | 6 | COMPILEFLAGS=-O3 -pipe -Wall -Wextra -pedantic -std=c++17 -DNDEBUG $(CWARN) $(CERROR) 7 | ifneq ($OS(OS), Windows_NT) 8 | UNAME_S := $(shell uname -s) 9 | ifeq ($(UNAME_S),Darwin) 10 | BISON ?= /opt/homebrew/opt/bison/bin/bison 11 | FLEX ?= /opt/homebrew/opt/flex/bin/flex 12 | LINKERFLAG=-O3 -lm -flto -DNDEBUG 13 | else 14 | BISON ?= bison 15 | FLEX ?= flex 16 | LINKERFLAG=-O3 -lm -flto -static -static-libgcc -DNDEBUG 17 | endif 18 | else # guessing what will work on Windows 19 | BISON ?= bison 20 | FLEX ?= flex 21 | LINKERFLAG=-O3 -lm -flto -static -static-libgcc -DNDEBUG 22 | endif 23 | 24 | 25 | .PHONY = all clean debug setdebug 26 | 27 | all: src/hddl-token.o src/hddl.o src/main.o src/sortexpansion.o src/parsetree.o src/util.o src/domain.o src/output.o src/parametersplitting.o src/cwa.o src/typeof.o src/shopWriter.o src/hpdlWriter.o src/hddlWriter.o src/htn2stripsWriter.o src/orderingDecomposition.o src/plan.o src/verify.o src/properties.o src/verification_encoding.o src/cmdline.o 28 | ${CXX} ${LINKERFLAG} $^ -o pandaPIparser 29 | 30 | %.o: %.cpp %.hpp src/hddl.hpp 31 | ${CXX} ${COMPILEFLAGS} -o $@ -c $< 32 | 33 | %.o: %.cpp src/hddl.hpp 34 | ${CXX} ${COMPILEFLAGS} -o $@ -c $< 35 | 36 | src/hddl-token.cpp: src/hddl.cpp src/hddl-token.l 37 | $(FLEX) --yylineno -o src/hddl-token.cpp src/hddl-token.l 38 | 39 | 40 | src/hddl.cpp: src/hddl.y 41 | $(BISON) -v -d -o src/hddl.cpp src/hddl.y 42 | 43 | src/hddl.hpp: src/hddl.cpp 44 | 45 | src/main.cpp: src/cmdline.h 46 | 47 | src/cmdline.c src/cmdline.h: src/options.ggo 48 | gengetopt --include-getopt --default-optional --unamed-opts --output-dir=src -i src/options.ggo 49 | 50 | 51 | setdebug: 52 | $(eval COMPILEFLAGS=-O0 -ggdb -pipe -Wall -Wextra -pedantic -std=c++17 $(CWARN) $(CERROR)) 53 | $(eval LINKERFLAG=-O0 -ggdb) 54 | 55 | debug: setdebug all 56 | 57 | 58 | clean: 59 | rm -f src/hddl-token.cpp 60 | rm -f src/hddl.cpp 61 | rm -f src/hddl.hpp 62 | rm -f src/*.o 63 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | hddl-token.cpp 3 | hddl.cpp 4 | hddl.hpp 5 | hddl.output 6 | -------------------------------------------------------------------------------- /src/cwa.cpp: -------------------------------------------------------------------------------- 1 | #include "cwa.hpp" 2 | #include "domain.hpp" 3 | #include 4 | #include 5 | 6 | vector init; 7 | vector> init_functions; 8 | vector goal; 9 | general_formula* goal_formula = NULL; 10 | 11 | bool operator< (const ground_literal& lhs, const ground_literal& rhs){ 12 | if (lhs.predicate < rhs.predicate) return true; 13 | if (lhs.predicate > rhs.predicate) return false; 14 | 15 | if (lhs.positive < rhs.positive) return true; 16 | if (lhs.positive > rhs.positive) return false; 17 | 18 | if (lhs.args < rhs.args) return true; 19 | if (lhs.args > rhs.args) return false; 20 | 21 | return false; // equal 22 | } 23 | 24 | void flatten_goal(){ 25 | if (goal_formula == NULL) return; 26 | vector>,vector >, additional_variables> > ex = goal_formula->expand(false); 27 | assert(ex.size() == 1); 28 | assert(ex[0].first.second.size() == 0); 29 | map access; 30 | for (auto x : ex[0].second){ 31 | string sort = x.second; 32 | assert(sorts[sort].size() == 1); // must be an actual constant 33 | access[x.first] = *sorts[sort].begin(); 34 | } 35 | 36 | for (variant l : ex[0].first.first){ 37 | if (holds_alternative(l)) 38 | assert(false); // goal may not contain conditional effects 39 | 40 | ground_literal gl; 41 | gl.predicate = get(l).predicate; 42 | gl.positive = get(l).positive; 43 | for (string v : get(l).arguments) gl.args.push_back(access[v]); 44 | goal.push_back(gl); 45 | } 46 | } 47 | 48 | 49 | map > int_sorts; 50 | map const_int; 51 | vector int_const; 52 | 53 | 54 | // fully instantiate predicate via recursion 55 | void fully_instantiate(int * inst, unsigned int pos, vector & arg_sorts, vector> & result){ 56 | if (pos == arg_sorts.size()){ 57 | vector instance(inst,inst + arg_sorts.size()); 58 | result.push_back(instance); 59 | return; 60 | } 61 | 62 | for (int c : int_sorts[arg_sorts[pos]]) { 63 | inst[pos] = c; 64 | fully_instantiate(inst,pos+1,arg_sorts,result); 65 | } 66 | } 67 | 68 | 69 | void compute_cwa(){ 70 | // transform sort representation to ints 71 | for (auto & s : sorts){ 72 | for (string c : s.second){ 73 | auto it = const_int.find(c); 74 | int id; 75 | if (it == const_int.end()) { 76 | id = const_int.size(); 77 | const_int[c] = id; 78 | int_const.push_back(c); 79 | } else id = it->second; 80 | int_sorts[s.first].push_back(id); 81 | } 82 | } 83 | 84 | 85 | // find predicates occurring negatively in preconditions and their types 86 | map>> neg_predicates_with_arg_sorts; 87 | 88 | for (task t : primitive_tasks) { 89 | vector literals = t.prec; 90 | for (conditional_effect ceff : t.ceff) 91 | for (literal l : ceff.condition) 92 | literals.push_back(l); 93 | 94 | for (literal l : literals) if (!l.positive) { 95 | vector argSorts; 96 | for (string v : l.arguments) for (auto x : t.vars) if (x.first == v) argSorts.push_back(x.second); 97 | assert(argSorts.size() == l.arguments.size()); 98 | neg_predicates_with_arg_sorts[l.predicate].insert(argSorts); 99 | } 100 | } 101 | 102 | // predicates negative in goal 103 | for (auto l : goal) if (!l.positive) { 104 | vector args; 105 | for (string c : l.args) args.push_back(sort_for_const(c)); 106 | neg_predicates_with_arg_sorts[l.predicate].insert(args); 107 | } 108 | 109 | map>> init_check; 110 | for(auto l : init){ 111 | vector args; 112 | for (string & arg : l.args) args.push_back(const_int[arg]); 113 | init_check[l.predicate].insert(args); 114 | } 115 | 116 | for (auto np : neg_predicates_with_arg_sorts){ 117 | set> instantiations; 118 | 119 | for (vector arg_sorts : np.second){ 120 | vector> inst; 121 | int * partial_instance = new int[arg_sorts.size()]; 122 | fully_instantiate(partial_instance, 0, arg_sorts, inst); 123 | delete[] partial_instance; 124 | 125 | for (vector & p : inst) if (instantiations.count(p) == 0){ 126 | instantiations.insert(p); 127 | if (init_check[np.first].count(p)) continue; 128 | ground_literal lit; lit.predicate = np.first; 129 | for (int arg : p) lit.args.push_back(int_const[arg]); 130 | lit.positive = false; 131 | init.push_back(lit); 132 | } 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/cwa.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __CWA 2 | #define __CWA 3 | 4 | #include 5 | #include 6 | #include "parsetree.hpp" 7 | 8 | using namespace std; 9 | 10 | struct ground_literal{ 11 | string predicate; 12 | bool positive; 13 | vector args; 14 | }; 15 | 16 | bool operator< (const ground_literal& lhs, const ground_literal& rhs); 17 | 18 | void flatten_goal(); 19 | void compute_cwa(); 20 | 21 | extern vector init; 22 | extern vector> init_functions; 23 | extern vector goal; 24 | extern general_formula* goal_formula; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/domain.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __DOMAIN 2 | #define __DOMAIN 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "sortexpansion.hpp" 9 | 10 | using namespace std; 11 | 12 | 13 | const string dummy_equal_literal = "__equal"; 14 | const string dummy_ofsort_literal = "__ofsort"; 15 | const string dummy_function_type = "__none"; 16 | const string numeric_funtion_type = "number"; 17 | const string method_precondition_action_name = "__method_precondition_"; 18 | const string immediate_method_precondition_action_name = "__immediate_method_precondition_"; 19 | 20 | 21 | struct literal{ 22 | bool positive; 23 | bool isConstantCostExpression; 24 | bool isCostChangeExpression; 25 | string predicate; 26 | vector arguments; 27 | int costValue; 28 | }; 29 | 30 | struct conditional_effect{ 31 | vector condition; 32 | literal effect; 33 | 34 | conditional_effect(vector cond, literal eff); 35 | }; 36 | 37 | struct task{ 38 | string name; 39 | int number_of_original_vars; // the first N variables are original, i.e. exist in the HDDL input file. The rest is artificial and was added by this parser for compilation 40 | vector> vars; 41 | vector prec; 42 | vector eff; 43 | vector ceff; 44 | vector constraints; 45 | vector costExpression; 46 | 47 | bool artificial; 48 | 49 | void check_integrity(); 50 | }; 51 | 52 | struct plan_step{ 53 | string task; 54 | string id; 55 | vector args; 56 | 57 | bool operator< (const plan_step& ps) const { 58 | return (id < ps.id); 59 | } 60 | }; 61 | 62 | struct method{ 63 | method(){adj_matrix_computed = false;}; 64 | string name; 65 | vector> vars; 66 | string at; 67 | vector atargs; 68 | vector ps; 69 | vector constraints; 70 | vector> ordering; 71 | 72 | void check_integrity(); 73 | 74 | bool is_sub_group(set & sset, set & beforeID, set & afterID); 75 | 76 | private: 77 | map> adj_matrix; 78 | bool adj_matrix_computed; 79 | void compute_adj_matrix(); 80 | }; 81 | 82 | 83 | // sort name and set of elements 84 | extern map > sorts; 85 | extern vector methods; 86 | extern vector primitive_tasks; 87 | extern vector abstract_tasks; 88 | extern map task_name_map; 89 | 90 | void flatten_tasks(bool compileConditionalEffects, bool linearConditionalEffectExpansion, bool encodeDisjunctivePreconditionsInMethods); 91 | void parsed_method_to_data_structures(bool compileConditionalEffects, bool linearConditionalEffectExpansion, bool encodeDisjunctivePreconditionsInMethods); 92 | void reduce_constraints(); 93 | void clean_up_sorts(); 94 | void remove_unnecessary_predicates(); 95 | 96 | 97 | set compute_constants_in_domain(); 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/hddl-token.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include "parsetree.hpp" 5 | #include "hddl.hpp" 6 | #define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; 7 | using namespace std; 8 | %} 9 | 10 | %option noyywrap 11 | %option yylineno 12 | %% 13 | \( {return '('; } 14 | \) {return ')'; } 15 | - {return '-'; } 16 | = {return '='; } 17 | \< {return '<'; } 18 | define {return KEY_DEFINE;} 19 | domain {return KEY_DOMAIN;} 20 | :domain {return KEY_DOMAIN;} 21 | problem {return KEY_PROBLEM;} 22 | :requirements {return KEY_REQUIREMENTS;} 23 | :types {return KEY_TYPES;} 24 | :constants {return KEY_CONSTANTS;} 25 | :predicates {return KEY_PREDICATES;} 26 | :functions {return KEY_FUNCTIONS;} 27 | :task {return KEY_TASK;} 28 | :action {return KEY_ACTION;} 29 | :parameters {return KEY_PARAMETERS;} 30 | :precondition {return KEY_PRECONDITION;} 31 | :effect {return KEY_EFFECT;} 32 | :method {return KEY_METHOD;} 33 | :init {return KEY_INIT;} 34 | :goal {return KEY_GOAL;} 35 | :htn {return KEY_HTN;} 36 | :tihtn {return KEY_TIHTN;} 37 | :htnti {return KEY_TIHTN;} 38 | :objects {return KEY_OBJECTS;} 39 | :bound {return KEY_BOUND;} 40 | :utility {return KEY_UTILITY;} 41 | :include {return KEY_INCLUDE;} 42 | 43 | :subtasks {return KEY_TASKS;} 44 | :tasks {return KEY_TASKS;} 45 | :ordered-subtasks {return KEY_ORDER_TASKS;} 46 | :ordered-tasks {return KEY_ORDER_TASKS;} 47 | :ordering {return KEY_ORDER;} 48 | :order {return KEY_ORDER;} 49 | 50 | :constraints {return KEY_CONSTRAINTS;} 51 | :metric {return KEY_METRIC;} 52 | minimize {return KEY_MIMIZE;} 53 | 54 | :causal-links {return KEY_CAUSAL_LINKS;} 55 | :causallinks {return KEY_CAUSAL_LINKS;} 56 | 57 | and {return KEY_AND;} 58 | or {return KEY_OR;} 59 | not {return KEY_NOT;} 60 | imply {return KEY_IMPLY;} 61 | forall {return KEY_FORALL;} 62 | exists {return KEY_EXISTS;} 63 | when {return KEY_WHEN;} 64 | increase {return KEY_INCREASE;} 65 | 66 | typeof {return KEY_TYPEOF;} 67 | sortof {return KEY_TYPEOF;} 68 | 69 | 70 | [ \t\n\r] ; // whitespace 71 | ;.*[\n\r] ; // comments 72 | \?[a-zA-Z][a-zA-Z0-9\-_]* {yylval.sval = strdup(yytext); return VAR_NAME;} 73 | :[a-zA-Z][a-zA-Z0-9\-_]* {yylval.sval = strdup(yytext); return REQUIRE_NAME;} 74 | [a-zA-Z][a-zA-Z0-9\-_|]* {yylval.sval = strdup(yytext); return NAME;} 75 | [0-9]+\.[0-9]+ {yylval.fval = atof(yytext); return FLOAT;} 76 | [0-9]+ {yylval.ival = atoi(yytext); return INT;} 77 | %% 78 | /* 79 | 80 | NUMBER : [0-9][0-9]* '.'? [0-9]* | '.' [0-9]*; 81 | */ 82 | -------------------------------------------------------------------------------- /src/hddlWriter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __HDDLWRITER 2 | #define __HDDLWRITER 3 | 4 | #include "parsetree.hpp" 5 | 6 | void hddl_output(ostream & dout, ostream & pout, bool internalHDDLOutput, bool usedParsed, bool dontWriteConstantsIntoDomain, bool removeMethodPreconditions); 7 | 8 | 9 | tuple, 10 | vector, 11 | map, 12 | map > compute_local_type_hierarchy(); 13 | 14 | void print_indent(ostream & out, int indent, bool end = false); 15 | void print_var_and_const(ostream & out, var_and_const & vars); 16 | void print_formula(ostream & out, general_formula * f, int indent); 17 | void print_formula_for(ostream & out, general_formula * f, string topic); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/hpdlWriter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __HPDLWRITER 2 | #define __HPDLWRITER 3 | 4 | #include "parsetree.hpp" 5 | 6 | void write_instance_as_HPDL(ostream & dout, ostream & pout); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/htn2stripsWriter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "hddlWriter.hpp" 9 | #include "htn2stripsWriter.hpp" 10 | #include "parsetree.hpp" 11 | #include "hddl.hpp" 12 | #include "domain.hpp" 13 | #include "sortexpansion.hpp" 14 | #include "cwa.hpp" 15 | #include "properties.hpp" 16 | #include "util.hpp" 17 | 18 | using namespace std; 19 | 20 | void htn2strips_output(ostream & dout, ostream & pout){ 21 | 22 | auto sanitise = [&](string s){ 23 | if (s[0] == '_') return "t" + s; 24 | return s; 25 | }; 26 | 27 | 28 | set neg_pred; 29 | for (task t : primitive_tasks) for (literal l : t.prec) if (!l.positive) neg_pred.insert(l.predicate); 30 | for (task t : primitive_tasks) for (conditional_effect ceff : t.ceff) for (literal l : ceff.condition) if (!l.positive) neg_pred.insert(l.predicate); 31 | for (auto l : goal) if (!l.positive) neg_pred.insert(l.predicate); 32 | 33 | 34 | // TODO do this more intelligently 35 | dout << "(define (domain d)" << endl; 36 | dout << " (:requirements :strips :disjunctive-preconditions :negative-preconditions"; 37 | dout << ")" << endl; 38 | 39 | dout << endl; 40 | 41 | 42 | 43 | // TODO identical types are not recognised and are treated as a non-dag structure, which is not necessary 44 | dout << " (:types" << endl; 45 | vector sortsInOrder; 46 | map replacedSorts; 47 | map sortOfElement; 48 | set declaredSorts; 49 | for (sort_definition s : sort_definitions){ 50 | bool first = true; 51 | for (string ss : s.declared_sorts){ 52 | if (s.has_parent_sort){ 53 | if (first) dout << " "; 54 | first = false; 55 | dout << " " << ss; 56 | } else 57 | dout << " " << ss << endl; 58 | 59 | declaredSorts.insert(ss); 60 | } 61 | if (s.has_parent_sort){ 62 | dout << " - " << s.parent_sort, declaredSorts.insert(s.parent_sort); 63 | dout << endl; 64 | } 65 | } 66 | 67 | dout << " )" << endl; 68 | 69 | dout << endl; 70 | 71 | 72 | 73 | pout << "(define" << endl; 74 | pout << " (problem p)" << endl; 75 | pout << " (:domain d)" << endl; 76 | 77 | 78 | // determine which constants need to be declared in the domain 79 | set constants_in_domain = compute_constants_in_domain(); 80 | 81 | if (constants_in_domain.size()) dout << " (:constants" << endl; 82 | pout << " (:objects" << endl; 83 | for (auto x : sorts) { 84 | if (! declaredSorts.count(x.first)) continue; 85 | for (string s : x.second) 86 | if (!constants_in_domain.count(s)) 87 | pout << " " << sanitise(s) << " - " << sanitise(x.first) << endl; 88 | else 89 | dout << " " << sanitise(s) << " - " << sanitise(x.first) << endl; 90 | } 91 | 92 | pout << " )" << endl; 93 | 94 | if (constants_in_domain.size()) dout << " )" << endl << endl; 95 | 96 | 97 | 98 | 99 | // predicate definitions 100 | dout << " (:predicates" << endl; 101 | map sortReplace; 102 | map typeConstraint; 103 | for (auto & [s,_] : sorts) sortReplace[s] = s; 104 | 105 | for (auto [originalSort,replacement] : replacedSorts){ 106 | string oldSort = sortsInOrder[originalSort]; 107 | string newSort = sortsInOrder[replacement]; 108 | sortReplace[oldSort] = newSort; 109 | string predicateName = "p_sort_member_" + sanitise(oldSort); 110 | typeConstraint[oldSort] = predicateName; 111 | dout << " (" << predicateName << " ?x - " << sanitise(newSort) << ")" << endl; 112 | } 113 | 114 | for (auto p : predicate_definitions) for (int negative = 0; negative < 2; negative++){ 115 | if (negative) continue; // compile only for internal output 116 | dout << " ("; 117 | if (negative) dout << "not_"; 118 | dout << sanitise(p.name); 119 | 120 | // arguments 121 | for (size_t arg = 0; arg < p.argument_sorts.size(); arg++) 122 | dout << " ?var" << arg << " - " << sanitise(sortReplace[p.argument_sorts[arg]]); 123 | 124 | dout << ")" << endl; 125 | } 126 | 127 | dout << " )" << endl; 128 | dout << endl; 129 | 130 | 131 | bool hasActionCosts = metric_target != dummy_function_type; 132 | 133 | // functions (for cost expressions) 134 | if (parsed_functions.size() && hasActionCosts){ 135 | dout << " (:functions" << endl; 136 | for(auto f : parsed_functions){ 137 | dout << " (" << sanitise(f.first.name); 138 | for (size_t arg = 0; arg < f.first.argument_sorts.size(); arg++) 139 | dout << " ?var" << arg << " - " << sanitise(f.first.argument_sorts[arg]); 140 | dout << ") - " << f.second << endl; 141 | } 142 | dout << " )" << endl; 143 | dout << endl; 144 | } 145 | 146 | // abstract tasks 147 | dout << " (:tasks " << endl; 148 | for (parsed_task a : parsed_abstract){ 149 | dout << " ("; 150 | dout << sanitise(a.name); 151 | for (auto [v,s] : a.arguments->vars){ 152 | dout << " "; 153 | dout << sanitise(v) << " - " << sanitise(sortReplace[s]); 154 | } 155 | dout << ")" << endl; 156 | } 157 | for (parsed_task a : parsed_primitive){ 158 | dout << " ("; 159 | dout << sanitise(a.name); 160 | for (auto [v,s] : a.arguments->vars){ 161 | dout << " "; 162 | dout << sanitise(v) << " - " << sanitise(sortReplace[s]); 163 | } 164 | dout << ")" << endl; 165 | } 166 | dout << " )" << endl; 167 | dout << endl; 168 | 169 | // decomposition methods 170 | for (auto [atname,ms] : parsed_methods) for (parsed_method m : ms){ 171 | dout << " (:method "; 172 | dout << sanitise(m.name) << endl; 173 | dout << " :parameters ("; 174 | bool first = true; 175 | for (auto [v,s] : m.vars->vars){ 176 | if (!first) dout << " "; 177 | first = false; 178 | dout << sanitise(v) << " - " << sanitise(sortReplace[s]); 179 | } 180 | dout << ")" << endl; 181 | 182 | // AT 183 | dout << " :task ("; 184 | dout << sanitise(atname); 185 | map atConstants; 186 | for (auto [v,s] : m.newVarForAT) 187 | atConstants[v] = *sorts[s].begin(); 188 | 189 | for (string v : m.atArguments) { 190 | if (atConstants.count(v)) 191 | v = atConstants[v]; 192 | dout << " " << sanitise(v); 193 | } 194 | dout << ")" << endl; 195 | 196 | 197 | if (!m.prec->isEmpty() || !m.tn->constraint->isEmpty()){ 198 | general_formula * precFormula = m.prec; 199 | if (m.prec->isEmpty()) 200 | precFormula = m.tn->constraint; 201 | else if (!m.tn->constraint->isEmpty()){ 202 | precFormula = new general_formula(); 203 | precFormula->type = AND; 204 | precFormula->subformulae.push_back(m.prec); 205 | precFormula->subformulae.push_back(m.tn->constraint); 206 | } 207 | 208 | print_formula_for(dout,precFormula,":precondition"); 209 | } 210 | 211 | if (!m.eff->isEmpty()) 212 | print_formula_for(dout,m.eff,":effect"); 213 | 214 | // subtasks 215 | vector liftedTopSort = liftedPropertyTopSort(m.tn); 216 | if (isTopSortTotalOrder(liftedTopSort,m.tn)){ 217 | dout << " :tasks (" << endl; 218 | map idMap; 219 | for (sub_task* t : m.tn->tasks) idMap[t->id] = t; 220 | for (string id : liftedTopSort){ 221 | dout << " (" << sanitise(idMap[id]->task); 222 | print_var_and_const(dout,*idMap[id]->arguments); 223 | dout << ")" << endl; 224 | } 225 | dout << " )" << endl; 226 | } else { 227 | for (sub_task * task : m.tn->tasks){ 228 | dout << " :tasks (" << sanitise(task->id) << " (" << sanitise(task->task); 229 | print_var_and_const(dout,*task->arguments); 230 | dout << "))" << endl; 231 | } 232 | //dout << " )" << endl; 233 | if (m.tn->ordering.size()){ 234 | // ordering of subtasks 235 | dout << " :ordering (" << endl; 236 | for (auto p : m.tn->ordering) 237 | dout << " (" << sanitise(p->first) << " " << sanitise(p->second) << ")" << endl; 238 | dout << " )" << endl; 239 | } 240 | } 241 | 242 | 243 | dout << " )" << endl << endl; 244 | } 245 | 246 | 247 | // actions 248 | for (parsed_task p : parsed_primitive){ 249 | dout << " (:action " << sanitise(p.name) << endl; 250 | dout << " :parameters ("; 251 | bool first = true; 252 | for (auto [v,s] : p.arguments->vars){ 253 | if (!first) dout << " "; 254 | first = false; 255 | dout << sanitise(v) << " - " << sanitise(sortReplace[s]); 256 | } 257 | dout << ")" << endl; 258 | 259 | dout << " :task ("; 260 | dout << sanitise(p.name); 261 | dout << " "; 262 | first = true; 263 | for (auto [v,s] : p.arguments->vars){ 264 | if (!first) dout << " "; 265 | first = false; 266 | dout << sanitise(v); 267 | } 268 | dout << ")" << endl; 269 | 270 | 271 | if (!p.prec->isEmpty()) 272 | print_formula_for(dout,p.prec,":precondition"); 273 | else 274 | dout << " :precondition ()" << endl; 275 | if (!p.eff->isEmpty()) 276 | print_formula_for(dout,p.eff,":effect"); 277 | else 278 | dout << " :effect ()" << endl; 279 | 280 | dout << " )" << endl; 281 | } 282 | 283 | dout << ")" << endl; 284 | 285 | 286 | bool instance_is_classical = true; 287 | for (task t : abstract_tasks) 288 | if (t.name == "__top") instance_is_classical = false; 289 | 290 | for (parsed_task t : parsed_abstract) 291 | if (t.name == "__top") instance_is_classical = false; 292 | 293 | /* 294 | if (! instance_is_classical){ 295 | pout << " (:htn" << endl; 296 | pout << " :parameters ()" << endl; 297 | pout << " :subtasks (and ("; 298 | pout << "t"; 299 | pout << "__top))" << endl; 300 | pout << " )" << endl; 301 | } 302 | */ 303 | 304 | pout << " (:init" << endl; 305 | for (auto gl : init){ 306 | if (!gl.positive) continue; // don't output negatives in normal mode 307 | pout << " ("; 308 | if (!gl.positive){ 309 | pout << "not"; 310 | pout << " ("; 311 | } 312 | pout << sanitise(gl.predicate); 313 | for (string c : gl.args) pout << " " << sanitise(c); 314 | if (!gl.positive) pout << ")"; 315 | pout << ")" << endl; 316 | } 317 | 318 | for (auto [oldType,predicate] : typeConstraint){ 319 | for (string c : sorts[oldType]) 320 | pout << " (" << sanitise(predicate) << " " << sanitise(c) << ")" << endl; 321 | } 322 | 323 | // metric 324 | if (hasActionCosts) 325 | for (auto f : init_functions){ 326 | pout << " (= (" << sanitise(f.first.predicate); 327 | for (auto c : f.first.args) pout << " " << sanitise(c); 328 | pout << ") " << f.second << ")" << endl; 329 | } 330 | 331 | pout << " )" << endl; 332 | 333 | if (! instance_is_classical) { 334 | pout << endl << " (:tasks ((t__top)))" << endl << endl; 335 | } 336 | 337 | if (goal_formula != nullptr && !goal_formula->isEmpty()){ 338 | print_formula_for(pout,goal_formula,"(:goal"); 339 | pout << " )" << endl; 340 | } 341 | 342 | if (hasActionCosts) 343 | pout << " (:metric minimize (" << sanitise(metric_target) << "))" << endl; 344 | 345 | 346 | pout << ")" << endl; 347 | } 348 | -------------------------------------------------------------------------------- /src/htn2stripsWriter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __HTN2STRIPSWRITER 2 | #define __HTN2STRIPSWRITER 3 | 4 | #include "parsetree.hpp" 5 | 6 | void htn2strips_output(ostream & dout, ostream & pout); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "cwa.hpp" 12 | #include "domain.hpp" 13 | #include "hddl.hpp" 14 | #include "hddlWriter.hpp" 15 | #include "hpdlWriter.hpp" 16 | #include "htn2stripsWriter.hpp" 17 | #include "output.hpp" 18 | #include "parametersplitting.hpp" 19 | #include "parsetree.hpp" 20 | #include "plan.hpp" 21 | #include "shopWriter.hpp" 22 | #include "sortexpansion.hpp" 23 | #include "typeof.hpp" 24 | #include "util.hpp" 25 | #include "verify.hpp" 26 | #include "verification_encoding.hpp" 27 | #include "properties.hpp" 28 | 29 | #include "cmdline.h" 30 | 31 | using namespace std; 32 | 33 | // declare parser function manually 34 | void run_parser_on_file(FILE* f, const char* filename); 35 | 36 | 37 | // parsed domain data structures 38 | bool has_typeof_predicate = false; 39 | bool method_preconditions_are_immediately_before = false; 40 | vector sort_definitions; 41 | vector predicate_definitions; 42 | vector parsed_primitive; 43 | vector parsed_abstract; 44 | map > parsed_methods; 45 | vector> parsed_functions; 46 | string metric_target = dummy_function_type; 47 | 48 | 49 | map > sorts; 50 | vector methods; 51 | vector primitive_tasks; 52 | vector abstract_tasks; 53 | 54 | map task_name_map; 55 | 56 | 57 | int main(int argc, char** argv) { 58 | cin.sync_with_stdio(false); 59 | cout.sync_with_stdio(false); 60 | int dfile = -1; 61 | int pfile = -1; 62 | int doutfile = -1; 63 | int poutfile = -1; 64 | bool splitParameters = true; 65 | bool compileConditionalEffects = true; 66 | bool linearConditionalEffectExpansion = false; 67 | bool encodeDisjunctivePreconditionsInMethods = false; 68 | bool compileGoalIntoAction = false; 69 | 70 | bool doVerifyEncoding = false; 71 | string verificationFile = ""; 72 | 73 | bool shopOutput = false; 74 | bool hpdlOutput = false; 75 | bool htn2stripsOutput = false; 76 | bool pureHddlOutput = false; 77 | bool hddlOutput = false; 78 | bool internalHDDLOutput = false; 79 | bool dontWriteConstantsIntoDomain = false; 80 | bool lenientVerify = false; 81 | bool verboseOutput = false; 82 | bool verifyPlan = false; 83 | bool useOrderInPlanVerification = true; 84 | bool convertPlan = false; 85 | bool showProperties = false; 86 | bool removeMethodPreconditions = false; 87 | int verbosity = 0; 88 | 89 | gengetopt_args_info args_info; 90 | if (cmdline_parser(argc, argv, &args_info) != 0) return 1; 91 | 92 | // set debug mode 93 | if (args_info.debug_given) { 94 | verboseOutput = true; 95 | verbosity = args_info.debug_arg; 96 | } 97 | if (args_info.no_colour_given) no_colors_in_output = true; 98 | if (args_info.no_split_parameters_given) splitParameters = false; 99 | if (args_info.keep_conditional_effects_given) compileConditionalEffects = false; 100 | if (args_info.linear_conditional_effect_given) { 101 | compileConditionalEffects = false; linearConditionalEffectExpansion = true; 102 | } 103 | if (args_info.encode_disjunctive_preconditions_in_htn_given) encodeDisjunctivePreconditionsInMethods = true; 104 | if (args_info.goal_action_given) compileGoalIntoAction = true; 105 | if (args_info.remove_method_preconditions_given) removeMethodPreconditions = true; 106 | 107 | if (args_info.shop_given) shopOutput = true; 108 | if (args_info.shop1_given) shopOutput = shop_1_compatability_mode = true; 109 | if (args_info.hpdl_given) hpdlOutput = true; 110 | if (args_info.hppdl_given) htn2stripsOutput = true; 111 | if (args_info.hddl_given) pureHddlOutput = true; 112 | if (args_info.processed_hddl_given) hddlOutput = true; 113 | if (args_info.internal_hddl_given) hddlOutput = internalHDDLOutput = true; 114 | if (args_info.no_domain_constants_given) dontWriteConstantsIntoDomain = true; 115 | 116 | if (args_info.verify_given){ 117 | verifyPlan = true; 118 | verbosity = args_info.verify_arg; 119 | } 120 | if (args_info.vverify_given){ 121 | verifyPlan = true; 122 | verbosity = 1; 123 | } 124 | if (args_info.vvverify_given){ 125 | verifyPlan = true; 126 | verbosity = 2; 127 | } 128 | if (args_info.lenient_given) verifyPlan = lenientVerify = true; 129 | if (args_info.verify_no_order_given) { 130 | verifyPlan = true; 131 | useOrderInPlanVerification = false; 132 | } 133 | 134 | if (args_info.verification_encoding_given){ 135 | doVerifyEncoding = true; 136 | verificationFile = args_info.verification_encoding_arg; 137 | } 138 | 139 | if (args_info.panda_converter_given) convertPlan = true; 140 | if (args_info.properties_given) showProperties = true; 141 | 142 | 143 | cerr << "pandaPIparser is configured as follows" << endl; 144 | cerr << " Colors in output: " << boolalpha << !no_colors_in_output << endl; 145 | if (showProperties){ 146 | cerr << " Mode: show instance properties" << endl; 147 | } else if (convertPlan){ 148 | cerr << " Mode: convert pandaPI plan" << endl; 149 | } else if (verifyPlan){ 150 | cerr << " Mode: plan verification" << endl; 151 | cerr << " Verbosity: " << verbosity << endl; 152 | cerr << " Lenient mode: " << boolalpha << lenientVerify << endl; 153 | cerr << " Ignore given order: " << !useOrderInPlanVerification << endl; 154 | } else { 155 | cerr << " Mode: parsing mode" << endl; 156 | cerr << " Parameter splitting: " << boolalpha << splitParameters << endl; 157 | cerr << " Conditional effects: "; 158 | if (compileConditionalEffects){ 159 | if (linearConditionalEffectExpansion) cerr << "linear encoding"; 160 | else cerr << "exponential encoding"; 161 | } else cerr << "keep"; 162 | cerr << endl; 163 | cerr << " Disjunctive preconditions as HTN: " << boolalpha << encodeDisjunctivePreconditionsInMethods << endl; 164 | cerr << " Replace goal with action: " << boolalpha << compileGoalIntoAction << endl; 165 | 166 | cerr << " Output: "; 167 | if (shopOutput) cerr << "SHOP2"; 168 | else if (shop_1_compatability_mode) cerr << "SHOP1"; 169 | else if (hpdlOutput) cerr << "HPDL"; 170 | else if (htn2stripsOutput) cerr << "HPPDL"; 171 | else if (pureHddlOutput) cerr << "HDDL (no transformations)"; 172 | else if (hddlOutput && internalHDDLOutput) cerr << "HDDL (internal)"; 173 | else if (hddlOutput && !internalHDDLOutput) cerr << "HDDL (with transformations)"; 174 | else cerr << "pandaPI format"; 175 | cerr << endl; 176 | } 177 | 178 | 179 | vector inputFiles; 180 | for (unsigned i = 0 ; i < args_info.inputs_num; i++) 181 | inputFiles.push_back(args_info.inputs[i]); 182 | 183 | if (inputFiles.size() > 0) dfile = 0; 184 | if (inputFiles.size() > 1) pfile = 1; 185 | if (inputFiles.size() > 2) doutfile = 2; 186 | if (inputFiles.size() > 3) poutfile = 3; 187 | 188 | if (dfile == -1){ 189 | if (convertPlan) 190 | cout << "You need to provide a plan as input." << endl; 191 | else 192 | cout << "You need to provide a domain and problem file as input." << endl; 193 | return 1; 194 | } 195 | 196 | // if we want to simplify a plan, just parse nothing 197 | if (convertPlan){ 198 | ifstream * plan = new ifstream(inputFiles[dfile]); 199 | ostream * outplan = &cout; 200 | if (pfile != -1){ 201 | ofstream * of = new ofstream(inputFiles[pfile]); 202 | if (!of->is_open()){ 203 | cout << "I can't open " << inputFiles[pfile] << "!" << endl; 204 | return 2; 205 | } 206 | outplan = of; 207 | } 208 | 209 | 210 | convert_plan(*plan, *outplan); 211 | return 0; 212 | } 213 | 214 | if (pfile == -1 && !convertPlan){ 215 | cout << "You need to provide a domain and problem file as input." << endl; 216 | return 1; 217 | } 218 | 219 | // open c-style file handle 220 | FILE *domain_file = fopen(inputFiles[dfile].c_str(), "r"); 221 | FILE *problem_file = fopen(inputFiles[pfile].c_str(), "r"); 222 | 223 | if (!domain_file) { 224 | cout << "I can't open " << inputFiles[dfile] << "!" << endl; 225 | return 2; 226 | } 227 | if (!problem_file) { 228 | cout << "I can't open " << inputFiles[pfile] << "!" << endl; 229 | return 2; 230 | } 231 | if (!shopOutput && !hpdlOutput && !hddlOutput && !pureHddlOutput && !htn2stripsOutput && poutfile != -1){ 232 | cout << "For ordinary pandaPI output, you may only specify one output file, but you specified two: " << inputFiles[doutfile] << " and " << inputFiles[poutfile] << endl; 233 | } 234 | 235 | // parsing of command line arguments has been completed 236 | 237 | 238 | // parse the domain file 239 | run_parser_on_file(domain_file, (char*) inputFiles[dfile].c_str()); 240 | run_parser_on_file(problem_file, (char*) inputFiles[pfile].c_str()); 241 | 242 | if (showProperties){ 243 | printProperties(); 244 | return 0; 245 | } 246 | 247 | if (pureHddlOutput || htn2stripsOutput) { 248 | // produce streams for output 249 | ostream * dout = &cout; 250 | ostream * pout = &cout; 251 | if (doutfile != -1){ 252 | ofstream * df = new ofstream(inputFiles[doutfile]); 253 | if (!df->is_open()){ 254 | cout << "I can't open " << inputFiles[doutfile] << "!" << endl; 255 | return 2; 256 | } 257 | dout = df; 258 | } 259 | if (poutfile != -1){ 260 | ofstream * pf = new ofstream(inputFiles[poutfile]); 261 | if (!pf->is_open()){ 262 | cout << "I can't open " << inputFiles[poutfile] << "!" << endl; 263 | return 2; 264 | } 265 | pout = pf; 266 | } 267 | if (pureHddlOutput) 268 | hddl_output(*dout,*pout, false, true, true, removeMethodPreconditions); 269 | else if (htn2stripsOutput) 270 | htn2strips_output(*dout,*pout); 271 | return 0; 272 | } 273 | 274 | 275 | if (!hpdlOutput) expand_sorts(); // add constants to all sorts 276 | 277 | // handle typeof-predicate 278 | if (!hpdlOutput && has_typeof_predicate) create_typeof(); 279 | 280 | if (compileGoalIntoAction) compile_goal_into_action(); 281 | if (removeMethodPreconditions) remove_method_preconditions(); 282 | 283 | // do not preprocess the instance at all if we are validating a solution 284 | if (verifyPlan){ 285 | ifstream * plan = new ifstream(inputFiles[doutfile]); 286 | if (! plan->good() ) { 287 | cerr << "Unable to open " << inputFiles[doutfile] << endl; 288 | return 1; 289 | } 290 | bool result = verify_plan(*plan, useOrderInPlanVerification, lenientVerify, verbosity); 291 | cout << "Plan verification result: "; 292 | if (result) cout << color(COLOR_GREEN,"true",MODE_BOLD); 293 | else cout << color(COLOR_RED,"false",MODE_BOLD); 294 | cout << endl; 295 | return result ? 0 : 1; 296 | } 297 | 298 | if (!hpdlOutput) { 299 | // flatten all primitive tasks 300 | flatten_tasks(compileConditionalEffects, linearConditionalEffectExpansion, encodeDisjunctivePreconditionsInMethods); 301 | // .. and the goal 302 | flatten_goal(); 303 | // create appropriate methods and expand method preconditions 304 | parsed_method_to_data_structures(compileConditionalEffects, linearConditionalEffectExpansion, encodeDisjunctivePreconditionsInMethods); 305 | } 306 | 307 | if (doVerifyEncoding) { 308 | encode_plan_verification(verificationFile); 309 | } 310 | 311 | if (shopOutput || hpdlOutput){ 312 | // produce streams for output 313 | ostream * dout = &cout; 314 | ostream * pout = &cout; 315 | if (doutfile != -1){ 316 | ofstream * df = new ofstream(inputFiles[doutfile]); 317 | if (!df->is_open()){ 318 | cout << "I can't open " << inputFiles[doutfile] << "!" << endl; 319 | return 2; 320 | } 321 | dout = df; 322 | } 323 | if (poutfile != -1){ 324 | ofstream * pf = new ofstream(inputFiles[poutfile]); 325 | if (!pf->is_open()){ 326 | cout << "I can't open " << inputFiles[poutfile] << "!" << endl; 327 | return 2; 328 | } 329 | pout = pf; 330 | } 331 | if (shopOutput) write_instance_as_SHOP(*dout,*pout); 332 | if (hpdlOutput) write_instance_as_HPDL(*dout,*pout); 333 | return 0; 334 | } 335 | 336 | 337 | // split methods with independent parameters to reduce size of grounding 338 | if (splitParameters) split_independent_parameters(); 339 | // cwa, but only if we actually want to compile negative preconditions 340 | if (!hpdlOutput || internalHDDLOutput) compute_cwa(); 341 | // simplify constraints as far as possible 342 | reduce_constraints(); 343 | clean_up_sorts(); 344 | remove_unnecessary_predicates(); 345 | 346 | // write to output 347 | if (verboseOutput) verbose_output(verbosity); 348 | else if (hddlOutput) { 349 | // produce streams for output 350 | ostream * dout = &cout; 351 | ostream * pout = &cout; 352 | if (doutfile != -1){ 353 | ofstream * df = new ofstream(inputFiles[doutfile]); 354 | if (!df->is_open()){ 355 | cout << "I can't open " << inputFiles[doutfile] << "!" << endl; 356 | return 2; 357 | } 358 | dout = df; 359 | } 360 | if (poutfile != -1){ 361 | ofstream * pf = new ofstream(inputFiles[poutfile]); 362 | if (!pf->is_open()){ 363 | cout << "I can't open " << inputFiles[poutfile] << "!" << endl; 364 | return 2; 365 | } 366 | pout = pf; 367 | } 368 | hddl_output(*dout,*pout, internalHDDLOutput, false, dontWriteConstantsIntoDomain, false); 369 | } else { 370 | ostream * dout = &cout; 371 | if (doutfile != -1){ 372 | ofstream * df = new ofstream(inputFiles[doutfile]); 373 | if (!df->is_open()){ 374 | cout << "I can't open " << inputFiles[doutfile] << "!" << endl; 375 | return 2; 376 | } 377 | dout = df; 378 | } 379 | simple_hddl_output(*dout); 380 | } 381 | } 382 | 383 | -------------------------------------------------------------------------------- /src/options.ggo: -------------------------------------------------------------------------------- 1 | package "pandaPIparser" 2 | version "0.1" 3 | purpose "The parser of the pandaPI planning system. Takes read an HTN problem written in HDDL and outputs it in pandaPI's internal simplified lifted format or one of other supported output formats" 4 | usage "./pandaPIparser [OPTIONS] domain.hddl problem.hddl output.htn" 5 | #description "" 6 | #versiontext "" 7 | 8 | args "--string-parser -u" 9 | 10 | 11 | ## use "-" for an option without a short option 12 | 13 | section "General Options" 14 | 15 | option "debug" d "activate debug mode and set the debug level" argoptional int default="1" 16 | option "no-colour" C "activate the no-colour mode, i.e. disable coloured output" flag off 17 | option "properties" p "only show the instances properties and exit" flag off 18 | 19 | 20 | section "Transformations" 21 | 22 | option "no-split-parameters" s "don't perform parameter splitting. Parameter splitting re-formulates methods in a way s.t. they have fewer groundings" flag off 23 | 24 | defgroup "conditionalEffects" groupdesc="Mode for handling conditional effects. Default is exponential encoding." 25 | groupoption "keep-conditional-effects" k "don't compile conditional effects into multiple actions. This compilation is active by default, but will lead to an exponential amount of actions in the number of conditional effects per actions. If it is turned off the conditional effects are written directly as-is to the output. The pandaPIgrounder can handle this, but not all planners might." group="conditionalEffects" 26 | groupoption "linear-conditional-effect" L "use a linear size encoding of conditional effects (by using the HTN structure). This has generally not a good performance in the planner" group="conditionalEffects" 27 | groupoption "exponential-conditional-effect" - "use the standard exponential encoding of conditional effects" group="conditionalEffects" 28 | 29 | option "encode-disjunctive-preconditions-in-htn" D "don't compile disjunctive preconditions into one action per element of the disjunction, but use the HTN structure instead" flag off 30 | option "goal-action" g "compile the state goal into an action" flag off 31 | 32 | option "remove-method-preconditions" m "remove all methods preconditions from the model (this alters the semantics of the model)" flag off 33 | 34 | option "verification-encoding" E "encode the verification problem for the given plan" optional string 35 | 36 | 37 | section "Output" sectiondesc="Default output is pandaPI's internal lifted representation. For formats that have both a domain and a problem file for output, you need to provide both as command line arguments instead of output.htn." 38 | defgroup "output" 39 | groupoption "shop" S "output in SHOP2 format" group="output" 40 | groupoption "shop1" 1 "output in SHOP1 format" group="output" 41 | groupoption "hpdl" H "output in HPDL format (for SIADEX)" group="output" 42 | groupoption "hppdl" R "output in HPPDL format (Ron Alford's format)" group="output" 43 | 44 | groupoption "hddl" h "output in HDDL format as is, i.e. without any transformations applied (even if they are activated)." group="output" 45 | groupoption "processed-hddl" P "output in processed HDDL, i.e. with transformations applied." group="output" 46 | groupoption "internal-hddl" i "output in processed HDDL, i.e. with transformations applied. This output will not try to conform with HDDL standards w.r.t. to action/task/method/predicate/object names, i.e. they may start with underscores or contain other illegal characters like ';' or '|'. This output is intended for debuggig." group="output" 47 | option "no-domain-constants" - "don't write constants into the domain" flag off 48 | 49 | section "Verifier" sectiondesc="These options only pertain to the plan verifier integrated into pandaPIparser. For plan verification, you need to call the verifier with three arguments: domain.hddl problem.hddl plan.txt" 50 | option "verify" v "activates the verifier" argoptional int values="0","1","2" default="0" 51 | option "vverify" V "activates the verifier with verbose output (i.e. verbosity level 1)" flag off 52 | option "vvverify" W "activates the verifier with very verbose output (i.e. verbosity level 2)" flag off 53 | option "lenient" l "switches the verifier to lenient mode. It will ignore difference is case and allow for all non letter characters in action, task, and method names to be replaced by underscores" flag off 54 | option "verify-no-order" o "ignore the order of subtasks given in the plan" flag off 55 | option "panda-converter" c "activates the pandaPI plan converter. Both the grounder and the parser may alter the planning problem s.t. the plan found by the engine might not be verifiable any more. With the converter, one can translate the found plan back into a verifiable plan. Run with two arguments: plan.in plan.out" flag off 56 | 57 | ##option "print-timings" T "print detailed timings of individual operations." flag off 58 | ##option "output-domain" O "write internal data structures representing the lifted input to standard out (only for debugging)." flag off 59 | ## 60 | ## 61 | ##section "Additional Inferences" 62 | ##option "invariants" i "use CPDL to infer lifted FAM groups and ground them." flag off 63 | ##option "h2" 2 "use H2 preprocessor to infer invariants." flag off 64 | ## 65 | ##section "Transformations" 66 | ##option "dont-remove-duplicates" D "don't remove duplcate actions, i.e. actions with the same preconditions and effects will be replaced by the same action. Currently, this applies only to method precondition actions." flag on 67 | ##option "no-empty-compilation" E "by default the grounder adds a zero-cost no-op action to otherwise empty methods. Needed by the pandaPIengine progression planner. This option disables the compilation" flag on 68 | ##option "no-literal-pruning" l "disables removal of statically true or false literals. Also literals that don't occur in preconditions are removed." flag on 69 | ##option "no-abstract-expansion" e "disables application of methods in the model. If an abstract task has only one applicable method, it will be applied directly in them model." flag on 70 | ##option "no-method-precondition-pruning" m "disables removal of actions without precondition and effects that where artificially inserted by the parser." flag on 71 | ##option "two-regularisation" t "transforms the model s.t. every method has at most two subtasks. Might be impossible for some partially ordered instances." flag off 72 | ## 73 | ##section "Grounding options" sectiondesc="These options only affect the performance of the grounder. Usually the defaults are fine. Please only change them if the grounder fails to ground the instance in a reasonable amount of time" 74 | ##option "static-precondition-checking-in-hierarchy-typing" c "check static preconditions already during hierarchy typing. This will increase the size of the hierarchy typing, but will make it more informed" flag off 75 | ##option "future-caching-by-initially-matched-precondition" f "enables future caching for the initially matched precondition in the generalised planning graph" flag off 76 | ##option "no-hierarchy-typing" n "disables hierarchy typing" flag on 77 | ## 78 | ## 79 | ##section "Output Mode" 80 | ## 81 | ##text "Default output mode is planner mode" # new line 82 | ##groupoption "planner" - "normal output for pandaPIplanner." group="outputmode" 83 | ##groupoption "sasplus" s "output SAS+ in Fast Downwards format. Note that this will only output the classical part of the model." group="outputmode" 84 | ##groupoption "hddl" H "output HDDL." group="outputmode" 85 | ##groupoption "no-output" g "only ground the instance, don't output anything." group="outputmode" 86 | ## 87 | ##defgroup "sasmode" 88 | ##text "Default SAS+ mode is as-input-sas-deletes" 89 | ##groupoption "as-input-sas-deletes" - "write the delete effects in the input (usually the minimally needed delete effects)" group="sasmode" 90 | ##groupoption "no-sas-deletes" N "don't output delete effects for SAS+ variables." group="sasmode" 91 | ##groupoption "all-sas-deletes" A "output all inferrable delete effects for each SAS+ variables." group="sasmode" 92 | ## 93 | ##text "\nFurther options" # new line 94 | ##option "force-sas" S "output all facts as SAS+ variables. Normally we use a special format for binary SAS+variables." flag off 95 | ##option "compile-negative" G "compile away negative SAS+ preconditions" flag off 96 | -------------------------------------------------------------------------------- /src/orderingDecomposition.cpp: -------------------------------------------------------------------------------- 1 | #include "orderingDecomposition.hpp" 2 | #include 3 | #include 4 | #include 5 | 6 | bool order_decomposition_matrix[2048][2048]; 7 | 8 | order_decomposition* extract_order_decomposition_dfs(vector & ids, vector bitmask); 9 | 10 | 11 | order_decomposition* try_extract_order_decomposition(vector & ids, vector bitmask, set bitmask_set, set split, bool & success){ 12 | success = false; 13 | 14 | // check 15 | bool anyOrder = false; 16 | bool allAfter = true; 17 | 18 | for (size_t ax = 0; ax < ids.size(); ax++){ 19 | if (! bitmask_set.count(ax)) continue; 20 | if (! split.count(ax)) continue; 21 | for (size_t bx = 0; bx < ids.size(); bx++){ 22 | if (! bitmask_set.count(bx)) continue; 23 | if ( split.count(bx)) continue; 24 | 25 | if (order_decomposition_matrix[ax][bx] || order_decomposition_matrix[bx][ax]) anyOrder = true; 26 | if (!order_decomposition_matrix[ax][bx]) allAfter = false; 27 | } 28 | } 29 | 30 | if (anyOrder && (!allAfter)) return 0; 31 | vector first_set,second_set; 32 | for (int & b : bitmask) 33 | if (split.count(b)) first_set.push_back(b); 34 | else second_set.push_back(b); 35 | 36 | order_decomposition* first = extract_order_decomposition_dfs(ids, first_set); 37 | order_decomposition* second = extract_order_decomposition_dfs(ids, second_set); 38 | 39 | order_decomposition* ret = new order_decomposition; 40 | if (first) ret->elements.push_back(first); 41 | else ret->elements.push_back(ids[*first_set.begin()]); 42 | 43 | if (second) ret->elements.push_back(second); 44 | else ret->elements.push_back(ids[*second_set.begin()]); 45 | 46 | 47 | if (!anyOrder) ret->isParallel = true; 48 | else ret->isParallel = false; 49 | 50 | success = true; 51 | return ret; 52 | } 53 | 54 | 55 | order_decomposition* extract_order_decomposition_dfs(vector & ids, vector bitmask){ 56 | //cout << "try for:"; 57 | //for (int b : bitmask) cout << " " << b; 58 | //cout << endl; 59 | 60 | if (bitmask.size() == 1) return 0; 61 | set bitmask_set; 62 | for (int &b : bitmask) bitmask_set.insert(b); 63 | 64 | for (size_t e = 0; e < bitmask.size(); e++){ 65 | set split; split.insert(bitmask[e]); 66 | bool succ; 67 | //cout << "try split on: " << e << endl; 68 | order_decomposition* ord = try_extract_order_decomposition(ids,bitmask,bitmask_set,split,succ); 69 | if (succ) return ord; 70 | } 71 | 72 | // try to find a subset to split on 73 | for (int i = 1; i < (1 << bitmask.size()); i++){ 74 | set split; 75 | for (int b = 0; b < 32; b++) if (i & (1 << b)) split.insert(bitmask[b]); 76 | bool succ; 77 | order_decomposition* ord = try_extract_order_decomposition(ids,bitmask,bitmask_set,split,succ); 78 | if (succ) return ord; 79 | } 80 | 81 | assert(false); 82 | return NULL; 83 | } 84 | 85 | 86 | order_decomposition* extract_order_decomposition(vector> ordering, vector ids){ 87 | if (!ids.size()) return NULL; 88 | if (ids.size() == 1) { 89 | order_decomposition* ret = new order_decomposition; 90 | ret->isParallel = false; 91 | ret->elements.push_back(ids[0]); 92 | return ret; 93 | } 94 | 95 | map ids_to_int; 96 | for (size_t i = 0; i < ids.size(); i++) ids_to_int[ids[i]] = i; 97 | for (size_t i = 0; i < ids.size(); i++) 98 | for (size_t j = 0; j < ids.size(); j++) 99 | order_decomposition_matrix[i][j] = false; 100 | 101 | for (pair & o : ordering) 102 | order_decomposition_matrix[ids_to_int[o.first]][ids_to_int[o.second]] = true; 103 | 104 | for (size_t k = 0; k < ids.size(); k++) 105 | for (size_t i = 0; i < ids.size(); i++) 106 | for (size_t j = 0; j < ids.size(); j++) 107 | if (order_decomposition_matrix[i][k] && order_decomposition_matrix[k][j]) 108 | order_decomposition_matrix[i][j] = true; 109 | 110 | vector bitmask; 111 | for (size_t i = 0; i < ids.size(); i++) bitmask.push_back(i); 112 | 113 | return extract_order_decomposition_dfs(ids,bitmask); 114 | } 115 | 116 | order_decomposition* simplify_order_decomposition(order_decomposition* ord){ 117 | vector> sub; 118 | for (variant s : ord->elements) 119 | if (holds_alternative(s)) 120 | sub.push_back(s); 121 | else 122 | sub.push_back(simplify_order_decomposition(get(s))); 123 | 124 | ord->elements.clear(); 125 | for (variant s : sub) 126 | if (holds_alternative(s)) 127 | ord->elements.push_back(s); 128 | else if (ord->isParallel != get(s)->isParallel) 129 | ord->elements.push_back(s); 130 | else { 131 | // expand 132 | for (variant ss : get(s)->elements) 133 | ord->elements.push_back(ss); 134 | } 135 | return ord; 136 | } 137 | 138 | -------------------------------------------------------------------------------- /src/orderingDecomposition.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __ORDERINGDECOMPOSITION 2 | #define __ORDERINGDECOMPOSITION 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | struct order_decomposition { 12 | bool isParallel; // if not it is sequential 13 | vector> elements; 14 | }; 15 | 16 | order_decomposition* extract_order_decomposition(vector> ordering, vector ids); 17 | order_decomposition* simplify_order_decomposition(order_decomposition* ord); 18 | 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/output.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __WRITER 2 | #define __WRITER 3 | 4 | #include 5 | 6 | using namespace std; 7 | 8 | void verbose_output(int verbosity); 9 | 10 | void hddl_output(ostream & dout, ostream & pout); 11 | void simple_hddl_output(ostream & dout); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/parametersplitting.cpp: -------------------------------------------------------------------------------- 1 | #include "domain.hpp" 2 | #include "parsetree.hpp" 3 | #include "parametersplitting.hpp" 4 | #include "util.hpp" 5 | #include 6 | using namespace std; 7 | 8 | void split_independent_parameters(){ 9 | // find static predicates 10 | 11 | set staticPredicates; 12 | for (auto p : predicate_definitions) staticPredicates.insert(p.name); 13 | for (task & prim : primitive_tasks) { 14 | for (literal & l : prim.eff) staticPredicates.erase(l.predicate); 15 | for (conditional_effect & ce : prim.ceff) staticPredicates.erase(ce.effect.predicate); 16 | } 17 | 18 | 19 | #ifndef NDEBUG 20 | cout << "Static predicates are: " << endl; 21 | for (string s : staticPredicates) 22 | cout << s << endl; 23 | #endif 24 | 25 | bool splittedSomeMethod = true; 26 | int i = 0; 27 | while (splittedSomeMethod){ 28 | splittedSomeMethod = false; 29 | 30 | set artificialTasks; 31 | for (task & prim : primitive_tasks) 32 | if (prim.artificial && prim.eff.size() == 0 && prim.ceff.size() == 0) // no effects ... 33 | artificialTasks.insert(prim.name); 34 | 35 | 36 | vector old = methods; 37 | methods.clear(); 38 | for(method m : old){ 39 | // find variables that occur only in one of the plan steps 40 | map>> variables_ps_id; 41 | set argumentsOfImmovables; 42 | for(plan_step ps : m.ps) { 43 | if (ps.task.rfind(immediate_method_precondition_action_name, 0) == 0) { 44 | for(string v : ps.args) argumentsOfImmovables.insert(v); 45 | } 46 | 47 | if (!artificialTasks.count(ps.task)) 48 | for(string v : ps.args) variables_ps_id[v].insert({ps.id,-1}); 49 | else { 50 | set vars_in_non_static; 51 | int pCount = 0; 52 | for (literal & l : task_name_map[ps.task].prec){ 53 | if (staticPredicates.count(l.predicate)){ 54 | for (string & a : l.arguments) 55 | variables_ps_id[a].insert({ps.id,pCount}); 56 | } else { 57 | for (string & a : l.arguments) 58 | vars_in_non_static.insert(a); 59 | } 60 | pCount++; 61 | } 62 | 63 | // handle constraints as if they were static condition (they are ...) 64 | for (literal & l : task_name_map[ps.task].constraints){ 65 | for (string & a : l.arguments) 66 | variables_ps_id[a].insert({ps.id,pCount}); 67 | pCount++; 68 | } 69 | 70 | for(string v : vars_in_non_static) 71 | variables_ps_id[v].insert({ps.id,-1}); 72 | } 73 | } 74 | 75 | #ifndef NDEBUG 76 | cout << "====================" << endl << "Method: " << m.name << endl; 77 | for (auto ps : m.ps) 78 | cout << "\t\tPS: " << ps.id << " " << ps.task << endl; 79 | for (auto [v,ss] : variables_ps_id){ 80 | cout << "\tvar: " << v << endl; 81 | for (auto [ps,prec] : ss) 82 | cout << "\t\t" << ps << " @ " << prec << endl; 83 | } 84 | #endif 85 | 86 | for (string v : argumentsOfImmovables) variables_ps_id.erase(v); 87 | 88 | map variableSorts; 89 | for(auto v : m.vars) variableSorts[v.first] = v.second; 90 | // don't consider variables that have at most one instantiation 91 | for(auto v : m.vars) if (sorts[v.second].size() < 2) variables_ps_id.erase(v.first); 92 | // can't split on arguments of abstract task 93 | for (string v : m.atargs) variables_ps_id.erase(v); 94 | // don't consider variables that are part of constraints 95 | for (literal l : m.constraints) variables_ps_id.erase(l.arguments[0]), variables_ps_id.erase(l.arguments[1]); 96 | 97 | // no variables can be splitted 98 | if (variables_ps_id.size() == 0) { methods.push_back(m); continue; } 99 | 100 | 101 | string largestSplittable = ""; 102 | // check for every splittable variable whether we can split it away. 103 | set beforeID, afterID; 104 | for (auto [vps,ss] : variables_ps_id) { 105 | set ordered_ps; 106 | set all_ps; 107 | // we can ignore order for static predicates on artificial tasks 108 | for (auto [ps,prec] : ss) { 109 | all_ps.insert(ps); 110 | if (prec == -1) ordered_ps.insert(ps); 111 | } 112 | 113 | // splitting on everything does not bring anything ... 114 | if (all_ps.size() == m.ps.size()) continue; 115 | 116 | #ifndef NDEBUG 117 | cout << "Var: " << vps << endl; 118 | for (string ps : ordered_ps) cout << "\t" << ps << endl; 119 | #endif 120 | 121 | set newbeforeID, newafterID; 122 | if (m.is_sub_group(ordered_ps, newbeforeID, newafterID)){ 123 | if (largestSplittable.size() == 0) 124 | largestSplittable = vps, beforeID = newbeforeID, afterID = newafterID; 125 | else if (sorts[variableSorts[vps]].size() > sorts[variableSorts[largestSplittable]].size()) 126 | largestSplittable = vps, beforeID = newbeforeID, afterID = newafterID; 127 | } 128 | } 129 | 130 | if (largestSplittable == "") { methods.push_back(m); continue; } 131 | 132 | splittedSomeMethod = true; 133 | 134 | #ifndef NDEBUG 135 | cout << "Largest Splittable: " << largestSplittable << endl; 136 | #endif 137 | 138 | //gather all variables that occur only in this group (might be more just this one) 139 | set> subgroup = variables_ps_id[largestSplittable]; 140 | set subgroupPSIDs; 141 | for (auto [id,_x] : subgroup) subgroupPSIDs.insert(id); 142 | 143 | // which variables can we add 144 | set variables_in_sub_group; 145 | for (auto [v,occ] : variables_ps_id){ 146 | bool ok = true; 147 | for (auto p : occ) ok &= subgroupPSIDs.count(p.first); 148 | if (ok) { 149 | variables_in_sub_group.insert(v); 150 | subgroup.insert(occ.begin(), occ.end()); 151 | } 152 | } 153 | #ifndef NDEBUG 154 | cout << "Variables in splitting subgroup:"; 155 | for (string v : variables_in_sub_group) cout << " " << v; 156 | cout << endl; 157 | #endif 158 | 159 | map variables_to_remove; 160 | for (auto v : variables_in_sub_group) 161 | variables_to_remove[v].size(); // insert into map 162 | 163 | method base; 164 | base.name = m.name; 165 | base.at = m.at; 166 | base.atargs = m.atargs; 167 | base.constraints = m.constraints; 168 | 169 | // create new abstract task 170 | task at; 171 | at.name = m.name + "_splitted_" + to_string(++i); 172 | // create a new method for the splitted task 173 | method sm; 174 | sm.name = "_splitting_method_" + at.name; // must start with an underscore s.t. this method will be removed by the solution compiler 175 | sm.at = at.name; 176 | 177 | 178 | // only take variables that are not to be removed 179 | map sorts_of_remaining; 180 | for(auto v : m.vars) 181 | if (variables_to_remove.count(v.first)) 182 | variables_to_remove[v.first] = v.second; 183 | else 184 | base.vars.push_back(v), sorts_of_remaining[v.first] = v.second; 185 | 186 | set smVars; // for duplicate check 187 | 188 | set splittedIDs; 189 | // put the plan steps in their respective methods 190 | for (plan_step ops : m.ps){ 191 | // check if this an artificial task which we may have to split 192 | set splitPrecs; 193 | set haveMinusOne; 194 | bool isSub = false; 195 | for (auto [id,prec] : subgroup){ 196 | if (id != ops.id) continue; 197 | if (prec == -1){ 198 | isSub = true; 199 | haveMinusOne.insert(id); 200 | } else { 201 | splitPrecs.insert(prec); 202 | } 203 | } 204 | 205 | if (splitPrecs.size() == 0) { 206 | if (!isSub) base.ps.push_back(ops); 207 | else sm.ps.push_back(ops); 208 | } else { 209 | // this is an artificial task that needs splitting 210 | task tMain = task_name_map[ops.task]; 211 | task tBase; plan_step pBase; 212 | task tSub; plan_step pSub; 213 | pBase.id = ops.id; 214 | pSub.id = ops.id; 215 | splittedIDs.insert(pSub.id); 216 | tBase.artificial = true; 217 | tSub.artificial = true; 218 | 219 | 220 | if (haveMinusOne.count(pBase.id)){ 221 | beforeID.insert(pBase.id); 222 | } 223 | 224 | // create names 225 | tBase.name = tMain.name + "_base"; pBase.task = tBase.name; 226 | tSub.name = tMain.name + "_split"; pSub.task = tSub.name; 227 | 228 | // contains only preconditions ... 229 | for (size_t i = 0; i < tMain.prec.size(); i++){ 230 | if (splitPrecs.count(i)) 231 | tSub.prec.push_back(tMain.prec[i]); 232 | else { 233 | bool needsSplit = false; 234 | for (string arg : tMain.prec[i].arguments) 235 | needsSplit |= variables_in_sub_group.count(arg); 236 | 237 | if (needsSplit) 238 | tSub.prec.push_back(tMain.prec[i]); 239 | else 240 | tBase.prec.push_back(tMain.prec[i]); 241 | } 242 | } 243 | // an constraints 244 | for (size_t i = 0; i < tMain.constraints.size(); i++){ 245 | if (splitPrecs.count(i + tMain.prec.size())) 246 | tSub.constraints.push_back(tMain.constraints[i]); 247 | else { 248 | bool needsSplit = false; 249 | for (string arg : tMain.constraints[i].arguments) 250 | needsSplit |= variables_in_sub_group.count(arg); 251 | 252 | if (needsSplit) 253 | tSub.constraints.push_back(tMain.constraints[i]); 254 | else 255 | tBase.constraints.push_back(tMain.constraints[i]); 256 | } 257 | } 258 | 259 | set varsSub, varsBase; 260 | for (literal l : tSub.prec) for (string v : l.arguments) varsSub.insert(v); 261 | for (literal l : tBase.prec) for (string v : l.arguments) varsBase.insert(v); 262 | for (literal l : tSub.constraints) for (string v : l.arguments) varsSub.insert(v); 263 | for (literal l : tBase.constraints) for (string v : l.arguments) varsBase.insert(v); 264 | 265 | // create variables 266 | for (size_t vnum = 0; vnum < tMain.vars.size(); vnum++){ 267 | auto vdecl = tMain.vars[vnum]; 268 | if (varsSub.count(vdecl.first)) { 269 | tSub.vars.push_back(vdecl); 270 | pSub.args.push_back(ops.args[vnum]); 271 | } 272 | if (varsBase.count(vdecl.first)) { 273 | tBase.vars.push_back(vdecl); 274 | pBase.args.push_back(ops.args[vnum]); 275 | } 276 | } 277 | tBase.number_of_original_vars = tBase.vars.size(); 278 | tSub.number_of_original_vars = tSub.vars.size(); 279 | 280 | tBase.check_integrity(); 281 | tSub.check_integrity(); 282 | 283 | primitive_tasks.push_back(tBase); task_name_map[tBase.name] = tBase; 284 | primitive_tasks.push_back(tSub); task_name_map[tSub.name] = tSub; 285 | 286 | base.ps.push_back(pBase); 287 | sm.ps.push_back(pSub); 288 | } 289 | } 290 | 291 | // ordering 292 | base.ordering.clear(); 293 | for (auto [b,a] : m.ordering){ 294 | int c = 0; 295 | if (subgroup.count({b,-1}) && !splittedIDs.count(b)) c++; 296 | if (subgroup.count({a,-1}) && !splittedIDs.count(a)) c++; 297 | if (c == 0) base.ordering.push_back({b,a}); 298 | if (c == 2) sm.ordering.push_back({b,a}); 299 | } 300 | 301 | for (plan_step ps : sm.ps){ 302 | if (splittedIDs.count(ps.id)) continue; 303 | for (string id : splittedIDs) 304 | sm.ordering.push_back({id,ps.id}); 305 | } 306 | 307 | // nps is the plan steps that is inserted into the base method 308 | plan_step nps; 309 | set npsVars; // duplicate check 310 | for (plan_step ps : sm.ps){ 311 | // variables 312 | for (string v : ps.args){ 313 | // if we don't remove it, it is an argument of the abstract task 314 | string sort; 315 | if (!variables_to_remove.count(v)){ 316 | sort = sorts_of_remaining[v]; 317 | if (!npsVars.count(v)){ 318 | npsVars.insert(v); 319 | at.vars.push_back(make_pair(v,sort)); 320 | nps.args.push_back(v); 321 | } 322 | } else 323 | sort = variables_to_remove[v]; 324 | 325 | if (!smVars.count(v)){ 326 | smVars.insert(v); 327 | sm.vars.push_back(make_pair(v,sort)); 328 | } 329 | } 330 | } 331 | 332 | // the new abstract task is done so push it 333 | at.number_of_original_vars = at.vars.size(); // does not matter as it will get pruned 334 | at.check_integrity(); 335 | abstract_tasks.push_back(at); 336 | task_name_map[at.name] = at; 337 | 338 | // add the new plan step to the base method 339 | nps.task = at.name; 340 | nps.id = "x_split_" + to_string(i); 341 | for (string b : beforeID) base.ordering.push_back({b,nps.id}); 342 | for (string a : afterID) base.ordering.push_back({nps.id,a}); 343 | 344 | base.ps.push_back(nps); 345 | 346 | sm.atargs = nps.args; 347 | #ifndef NDEBUG 348 | cout << "Checking splitting method" << endl; 349 | #endif 350 | sm.check_integrity(); 351 | methods.push_back(sm); 352 | 353 | #ifndef NDEBUG 354 | cout << "Checking base method" << endl; 355 | #endif 356 | base.check_integrity(); 357 | methods.push_back(base); 358 | } 359 | //break; 360 | } 361 | } 362 | 363 | -------------------------------------------------------------------------------- /src/parametersplitting.hpp: -------------------------------------------------------------------------------- 1 | void split_independent_parameters(); 2 | -------------------------------------------------------------------------------- /src/parsetree.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __PARSETREE 2 | #define __PARSETREE 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "domain.hpp" 10 | using namespace std; 11 | 12 | extern int task_id_counter; 13 | 14 | struct sort_definition{ 15 | vector declared_sorts; 16 | bool has_parent_sort; 17 | string parent_sort; 18 | }; 19 | 20 | struct var_declaration{ 21 | vector > vars; 22 | }; 23 | 24 | struct predicate_definition{ 25 | string name; 26 | vector argument_sorts; 27 | }; 28 | 29 | typedef set > additional_variables ; 30 | struct var_and_const{ 31 | vector vars; 32 | additional_variables newVar; // varname & sort 33 | }; 34 | 35 | struct function_expression{ 36 | bool isOnlyValue; 37 | int value; 38 | string name; 39 | var_and_const arguments; 40 | }; 41 | 42 | enum formula_type {EMPTY, AND, OR, FORALL, EXISTS, ATOM, NOTATOM, // formulae 43 | EQUAL, NOTEQUAL, OFSORT, NOTOFSORT, 44 | WHEN, // conditional effect 45 | VALUE, COST, COST_CHANGE // cost statement 46 | }; 47 | 48 | class general_formula{ 49 | public: 50 | formula_type type; 51 | vector subformulae; 52 | string predicate; 53 | var_and_const arguments; 54 | var_declaration qvariables; 55 | function_expression *value_increased, *increase_amount; 56 | 57 | string arg1; 58 | string arg2; 59 | int value; 60 | 61 | void negate(); 62 | bool isEmpty(); 63 | bool hasEquals(); 64 | bool hasExists(); 65 | bool hasForall(); 66 | // first: effect, second: additional precondition for that effect 67 | // if it is an uncompiled conditional effect, the additional prec will be empty 68 | vector>,vector >, additional_variables> > expand(bool compileConditionalEffects); 69 | bool isDisjunctive(); 70 | additional_variables variables_for_constants(); 71 | 72 | literal equalsLiteral(); 73 | literal atomLiteral(); 74 | pair >, additional_variables> forallVariableReplacement(); 75 | map existsVariableReplacement(); 76 | 77 | set occuringUnQuantifiedVariables(); 78 | 79 | general_formula* copyReplace(map& replace); 80 | }; 81 | 82 | 83 | struct parsed_task{ 84 | string name; 85 | var_declaration* arguments; 86 | general_formula* prec; 87 | general_formula* eff; 88 | }; 89 | 90 | 91 | struct sub_task{ 92 | string id; 93 | string task; 94 | var_and_const* arguments; 95 | }; 96 | 97 | struct parsed_task_network{ 98 | vector tasks; 99 | vector*> ordering; 100 | general_formula* constraint; 101 | }; 102 | 103 | struct parsed_method{ 104 | string name; 105 | vector atArguments; 106 | var_declaration* vars; 107 | additional_variables newVarForAT; // varname & sort 108 | general_formula* prec; 109 | general_formula* eff; 110 | parsed_task_network* tn; 111 | }; 112 | 113 | // global places to put data structures 114 | extern bool has_typeof_predicate; 115 | extern bool method_preconditions_are_immediately_before; 116 | extern vector sort_definitions; 117 | extern vector predicate_definitions; 118 | extern vector parsed_primitive; 119 | extern vector parsed_abstract; 120 | extern map > parsed_methods; 121 | extern vector> parsed_functions; 122 | extern string metric_target; 123 | 124 | 125 | string sort_for_const(string c); 126 | void compile_goal_into_action(); 127 | void remove_method_preconditions(); 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /src/plan.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __PLAN 2 | #define __PLAN 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "parsetree.hpp" 9 | 10 | 11 | struct instantiated_plan_step{ 12 | std::string name; 13 | std::vector arguments; 14 | bool declaredPrimitive; 15 | }; 16 | 17 | 18 | struct parsed_plan{ 19 | std::map tasks; 20 | std::vector primitive_plan; 21 | std::map pos_in_primitive_plan; 22 | std::map appliedMethod; 23 | std::map> subtasksForTask; 24 | std::vector root_tasks; 25 | 26 | std::map task_contained_in; 27 | }; 28 | 29 | parsed_plan parse_plan(istream & plan, int debugMode); 30 | 31 | void convert_plan(istream & plan, ostream & pout); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/properties.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "properties.hpp" 6 | #include "parsetree.hpp" 7 | 8 | using namespace std; 9 | 10 | void liftedPropertyTopSortDFS(string cur, map> & adj, map & colour, vector & liftedTopSort){ 11 | assert (colour[cur] != 1); 12 | if (colour[cur]) return; 13 | 14 | colour[cur] = 1; 15 | for (string & nei : adj[cur]) liftedPropertyTopSortDFS(nei,adj,colour, liftedTopSort); 16 | colour[cur] = 2; 17 | 18 | liftedTopSort.push_back(cur); 19 | } 20 | 21 | vector liftedPropertyTopSort(parsed_task_network* tn){ 22 | vector liftedTopSort; 23 | map> adj; 24 | for (pair * nei : tn->ordering) 25 | adj[nei->first].push_back(nei->second); 26 | 27 | map colour; 28 | 29 | for (sub_task* t : tn->tasks) 30 | if (!colour[t->id]) liftedPropertyTopSortDFS(t->id, adj, colour, liftedTopSort); 31 | 32 | reverse(liftedTopSort.begin(), liftedTopSort.end()); 33 | 34 | return liftedTopSort; 35 | } 36 | 37 | 38 | bool isTopSortTotalOrder(vector & liftedTopSort, parsed_task_network * tn){ 39 | for (size_t i = 1; i < liftedTopSort.size(); i++){ 40 | bool orderEnforced = false; 41 | for (pair * nei : tn->ordering) 42 | if (nei->first == liftedTopSort[i-1] && nei->second == liftedTopSort[i]){ 43 | orderEnforced = true; 44 | break; 45 | } 46 | if (!orderEnforced) return false; 47 | } 48 | return true; 49 | } 50 | 51 | 52 | 53 | bool recursionFindingDFS(string cur, map & colour){ 54 | if (colour[cur] == 1) return true; 55 | if (colour[cur]) return false; 56 | 57 | colour[cur] = 1; 58 | for (parsed_method & m : parsed_methods[cur]) 59 | for (sub_task* sub : m.tn->tasks) 60 | if (recursionFindingDFS(sub->task,colour)) return true; 61 | colour[cur] = 2; 62 | 63 | return false; 64 | } 65 | 66 | 67 | bool isRecursiveParentSort(string current, string target){ 68 | if (current == target) return true; 69 | for (sort_definition & sd : sort_definitions){ 70 | for (string & ss : sd.declared_sorts) 71 | if (current == ss){ 72 | if (!sd.has_parent_sort) continue; 73 | if (isRecursiveParentSort(sd.parent_sort, target)) return true; 74 | } 75 | } 76 | return false; 77 | } 78 | 79 | void printProperties(){ 80 | // determine lifted instance properties and print them 81 | 82 | // 1. Total order 83 | bool totalOrder = true; 84 | for (auto & [_,ms] : parsed_methods) 85 | for (auto & m : ms){ 86 | if (m.tn->tasks.size() < 2) continue; 87 | // do topsort 88 | vector liftedTopSort = liftedPropertyTopSort(m.tn); 89 | 90 | if (!isTopSortTotalOrder(liftedTopSort,m.tn)){ 91 | cout << "Partially Ordered Method: " << m.name << endl; 92 | totalOrder = false; 93 | } 94 | } 95 | 96 | 97 | cout << "Instance is totally-ordered: "; 98 | if (totalOrder) cout << "yes" << endl; else cout << "no" << endl; 99 | 100 | 101 | // 2. recursion 102 | map colour; 103 | bool hasLiftedRecursion = recursionFindingDFS("__top",colour); 104 | 105 | cout << "Instance is acyclic: "; 106 | if (!hasLiftedRecursion) cout << "yes" << endl; else cout << "no" << endl; 107 | 108 | 109 | // 3. empty methods 110 | bool emptyMethod = false; 111 | for (auto & [_,ms] : parsed_methods) 112 | for (auto & m : ms){ 113 | if (m.tn->tasks.size() == 0) emptyMethod = true; 114 | } 115 | 116 | 117 | cout << "Instance has empty methods: "; 118 | if (emptyMethod) cout << "yes" << endl; else cout << "no" << endl; 119 | 120 | 121 | 122 | 123 | // requirements 124 | cout << "Requirements:" << endl; 125 | cout << "\t:hierarchy" << endl; 126 | if (sort_definitions.size()) cout << "\t:typing" << endl; 127 | bool hasEquals = false; 128 | for (auto & [_,ms] : parsed_methods) 129 | for (auto & m : ms) 130 | hasEquals |= m.prec->hasEquals() || m.eff->hasEquals(); 131 | for (auto & p : parsed_primitive) 132 | hasEquals |= p.prec->hasEquals() || p.eff->hasEquals(); 133 | if (hasEquals) cout << "\t:equality" << endl; 134 | 135 | 136 | bool exists_prec = false; 137 | for (auto & [_,ms] : parsed_methods) 138 | for (auto & m : ms) 139 | exists_prec |= m.prec->hasExists(); 140 | for (auto & p : parsed_primitive) 141 | exists_prec |= p.prec->hasExists(); 142 | if (exists_prec) cout << "\t:existential-preconditions" << endl; 143 | 144 | bool forall_prec = false; 145 | for (auto & [_,ms] : parsed_methods) 146 | for (auto & m : ms) 147 | forall_prec |= m.prec->hasForall(); 148 | for (auto & p : parsed_primitive) 149 | forall_prec |= p.prec->hasForall(); 150 | if (forall_prec) cout << "\t:universal-preconditions" << endl; 151 | 152 | bool forall_eff = false; 153 | for (auto & [_,ms] : parsed_methods) 154 | for (auto & m : ms) 155 | forall_eff |= m.eff->hasForall(); 156 | for (auto & p : parsed_primitive) 157 | forall_eff |= p.eff->hasForall(); 158 | if (forall_eff) cout << "\t:universal-effects" << endl; 159 | 160 | 161 | bool method_preconditon = false; 162 | for (auto & [_,ms] : parsed_methods) 163 | for (auto & m : ms) 164 | method_preconditon |= !m.prec->isEmpty(); 165 | if (method_preconditon) cout << "\t:method-preconditions" << endl; 166 | 167 | 168 | for (auto & [_,ms] : parsed_methods) 169 | for (auto & m : ms){ 170 | for (sub_task * sub : m.tn->tasks){ 171 | // quadratic 172 | for (parsed_task prim : parsed_primitive){ 173 | if (sub->task != prim.name) continue; 174 | for (size_t i = 0; i < prim.arguments->vars.size(); i++){ 175 | string primArgType = prim.arguments->vars[i].second; 176 | string method_var = sub->arguments->vars[i]; 177 | 178 | for (pair a : m.vars->vars){ 179 | if (method_var == a.first){ 180 | if (primArgType != a.second){ 181 | if (!isRecursiveParentSort(a.second, primArgType)){ 182 | cout << "Method: " << m.name << endl; 183 | cout << "\tVariable: " << method_var << endl; 184 | cout << "\tSubtask: " << sub->id << endl; 185 | cout << "\t\tTask argument: " << primArgType << endl; 186 | cout << "\t\tvariable: " << a.second << endl; 187 | } 188 | } 189 | } 190 | } 191 | } 192 | } 193 | for (parsed_task prim : parsed_abstract){ 194 | if (sub->task != prim.name) continue; 195 | for (size_t i = 0; i < prim.arguments->vars.size(); i++){ 196 | string primArgType = prim.arguments->vars[i].second; 197 | string method_var = sub->arguments->vars[i]; 198 | 199 | for (pair a : m.vars->vars){ 200 | if (method_var == a.first){ 201 | if (primArgType != a.second){ 202 | if (!isRecursiveParentSort(a.second, primArgType)){ 203 | cout << "Method: " << m.name << endl; 204 | cout << "\tVariable: " << method_var << endl; 205 | cout << "\tSubtask: " << sub->id << endl; 206 | cout << "\t\tTask argument: " << primArgType << endl; 207 | cout << "\t\tvariable: " << a.second << endl; 208 | } 209 | 210 | } 211 | break; 212 | } 213 | } 214 | } 215 | } 216 | 217 | } 218 | } 219 | 220 | 221 | } 222 | 223 | -------------------------------------------------------------------------------- /src/properties.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __PROPERTIES 2 | #define __PROPERTIES 3 | 4 | #include 5 | #include "parsetree.hpp" 6 | 7 | void printProperties(); 8 | 9 | vector liftedPropertyTopSort(parsed_task_network* tn); 10 | bool isTopSortTotalOrder(vector & liftedTopSort, parsed_task_network * tn); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/shopWriter.cpp: -------------------------------------------------------------------------------- 1 | #include "shopWriter.hpp" 2 | #include "cwa.hpp" 3 | #include "orderingDecomposition.hpp" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include // for ffs 9 | #include 10 | 11 | 12 | const string shop_type_predicate_prefix = "(type_"; 13 | 14 | bool shop_1_compatability_mode = false; 15 | 16 | string sanitise(string in){ 17 | if (in == "call") in = "_call"; 18 | 19 | //if (!shop_1_compatability_mode) return in; 20 | 21 | replace(in.begin(),in.end(),'_','-'); 22 | replace(in.begin(),in.end(),'|','-'); 23 | // replace leading minus by training 24 | if (in[0] == '-') return "x" + in; 25 | return in; 26 | } 27 | 28 | void write_literal_list_SHOP(ostream & dout, vector & literals){ 29 | bool first = true; 30 | for (literal & l : literals){ 31 | if (!first) dout << " "; else first=false; 32 | dout << "("; 33 | if (!l.positive) dout << "not ("; 34 | dout << sanitise(l.predicate); 35 | for (string arg : l.arguments) dout << " " << sanitise(arg); 36 | if (!l.positive) dout << ")"; 37 | dout << ")"; 38 | } 39 | } 40 | 41 | 42 | 43 | void write_shop_order_decomposition(ostream & dout, order_decomposition* order, map & idmap, set names_of_primitives){ 44 | if (!order) return; 45 | dout << "("; 46 | if (order->isParallel) dout << ":unordered "; 47 | 48 | bool first = true; 49 | for (variant elem : order->elements){ 50 | if (first) first = false; else dout << " "; 51 | if (holds_alternative(elem)){ 52 | plan_step ps = idmap[get(elem)]; 53 | dout << "("; 54 | if (names_of_primitives.count(ps.task)) dout << "!"; 55 | dout << sanitise(ps.task); 56 | for (string & arg : ps.args) dout << " " << sanitise(arg); 57 | dout << ")"; 58 | } else 59 | write_shop_order_decomposition(dout, get(elem),idmap, names_of_primitives); 60 | } 61 | 62 | dout << ")"; 63 | } 64 | 65 | 66 | void write_instance_as_SHOP(ostream & dout, ostream & pout){ 67 | dout << "(defdomain domain (" << endl; 68 | 69 | set names_of_primitives; // this is needed for writing the !'s in methods 70 | // output all actions, in shop they are named operators 71 | for (task & prim : primitive_tasks){ 72 | if (prim.name.rfind(method_precondition_action_name, 0) == 0) continue; // don't output method precondition action ... they will be part of the output 73 | if (prim.name.rfind(immediate_method_precondition_action_name, 0) == 0) continue; // don't output method precondition action ... they will be part of the output 74 | names_of_primitives.insert(prim.name); 75 | dout << " (:operator (!" << sanitise(prim.name); 76 | // arguments 77 | for (pair var : prim.vars) 78 | dout << " " << sanitise(var.first); 79 | dout << ")" << endl; 80 | 81 | // precondition 82 | dout << " ;; preconditions" << endl; 83 | dout << " (" << endl; 84 | dout << " "; 85 | for (size_t i = 0; i < prim.vars.size(); i++){ 86 | if (i) dout << " "; 87 | dout << sanitise(shop_type_predicate_prefix) << sanitise(prim.vars[i].second) << " " << sanitise(prim.vars[i].first) << ")"; 88 | } 89 | dout << endl << " "; 90 | write_literal_list_SHOP(dout, prim.prec); 91 | // write constraints 92 | for (literal & constraint : prim.constraints){ 93 | dout << " ("; 94 | if (!constraint.positive) dout << "not ("; 95 | dout << "call "; 96 | if (shop_1_compatability_mode) dout << "equal"; else dout << "="; 97 | for (string arg : constraint.arguments) dout << " " << sanitise(arg); 98 | if (!constraint.positive) dout << ")"; 99 | dout << ")"; 100 | } 101 | dout << endl << " )" << endl; 102 | 103 | vector add, del; 104 | for (literal & l : prim.eff) 105 | if (l.positive) add.push_back(l); else { 106 | del.push_back(l); 107 | del[del.size()-1].positive = true; 108 | } 109 | 110 | 111 | // delete effects 112 | dout << " ;; delete effects" << endl; 113 | dout << " ("; 114 | write_literal_list_SHOP(dout, del); 115 | dout << ")" << endl; 116 | 117 | // add effects 118 | dout << " ;; add effects" << endl; 119 | dout << " ("; 120 | write_literal_list_SHOP(dout, add); 121 | dout << ")" << endl; 122 | 123 | // costs 124 | if (prim.costExpression.size()){ 125 | int value = 0; 126 | for (literal & cexpr : prim.costExpression){ 127 | if (!cexpr.isConstantCostExpression){ 128 | cerr << "Primitive action \"" << prim.name << "\" does not have constant costs" << endl; 129 | return; 130 | } 131 | 132 | value += cexpr.costValue; 133 | } 134 | dout << " " << value << endl; 135 | } 136 | 137 | dout << " )" << endl; 138 | } 139 | 140 | 141 | for (method & m : methods){ 142 | dout << " (:method (" << sanitise(m.at); 143 | for (string & atarg : m.atargs) 144 | dout << " " << sanitise(atarg); 145 | dout << ")" << endl; 146 | // method name 147 | dout << " " << sanitise(m.name) << endl; 148 | 149 | // find the corresponding at 150 | task at; bool found = false; 151 | for (task & a : abstract_tasks) 152 | if (a.name == m.at){ 153 | at = a; 154 | found = true; 155 | break; 156 | } 157 | 158 | if (! found) { 159 | cerr << "method " << m.name << " decomposes unknown task " << m.at << endl; 160 | _Exit(1); 161 | } 162 | 163 | 164 | // method precondition 165 | dout << " (" << endl << " "; 166 | // typing constraints of the AT 167 | for (size_t i = 0; i < at.vars.size(); i++){ 168 | if (i) dout << " "; 169 | dout << sanitise(shop_type_predicate_prefix) << sanitise(at.vars[i].second) << " " << sanitise(m.atargs[i]) << ")"; 170 | } 171 | dout << endl << " "; 172 | // typing of the method 173 | bool first = true; 174 | for (pair & v : m.vars){ 175 | if (first) first = false; else dout << " "; 176 | dout << sanitise(shop_type_predicate_prefix) << sanitise(v.second) << " " << sanitise(v.first) << ")"; 177 | } 178 | dout << endl << " "; 179 | // method precondition in the input 180 | set tasksToWrite; 181 | for (plan_step & ps : m.ps){ 182 | if (ps.task.rfind(method_precondition_action_name, 0) == string::npos && ps.task.rfind(immediate_method_precondition_action_name, 0) == string::npos) continue; 183 | found = false; 184 | for (task & p : primitive_tasks) 185 | if (p.name == ps.task){ 186 | found = true; 187 | assert(p.eff.size() == 0); 188 | write_literal_list_SHOP(dout,p.prec); 189 | break; 190 | } 191 | if (!found) tasksToWrite.insert(ps.task); 192 | //assert(found); 193 | } 194 | 195 | dout << endl << " )" << endl; 196 | 197 | // subtasks 198 | 199 | vector ids; 200 | map idmap; 201 | for (plan_step & ps : m.ps){ 202 | if (tasksToWrite.count(ps.task) == 0 && ps.task.rfind(method_precondition_action_name, 0) == 0) continue; 203 | if (tasksToWrite.count(ps.task) == 0 && ps.task.rfind(immediate_method_precondition_action_name, 0) == 0) continue; 204 | ids.push_back(ps.id); 205 | idmap[ps.id] = ps; 206 | } 207 | 208 | vector> filtered_ordering; 209 | for (pair & ord : m.ordering) 210 | if (idmap.count(ord.first) && idmap.count(ord.second)) 211 | filtered_ordering.push_back(ord); 212 | // else the ordering pertains to the method precondition. At this point, there can be only one so just ignoring these constraints is ok -- they cannot introduce transitive constraints, that are relevant 213 | 214 | if (ids.size()){ 215 | order_decomposition* order = extract_order_decomposition(filtered_ordering,ids); 216 | order = simplify_order_decomposition(order); 217 | dout << " "; 218 | write_shop_order_decomposition(dout,order,idmap,names_of_primitives); 219 | dout << endl; 220 | } else { 221 | // empty method 222 | dout << " ()" << endl; 223 | } 224 | 225 | 226 | 227 | dout << " )" << endl; 228 | } 229 | 230 | 231 | dout << "))" << endl; 232 | 233 | 234 | //------------------------------------------- 235 | // write the problem instance 236 | pout << "(defproblem problem domain " << endl; 237 | pout << " (" << endl; 238 | // initial state 239 | for (ground_literal & gl : init){ 240 | if (!gl.positive) continue; 241 | pout << " (" << sanitise(gl.predicate); 242 | for (string & arg : gl.args) 243 | pout << " " << sanitise(arg); 244 | pout << ")" << endl; 245 | } 246 | 247 | // type assertions 248 | for (auto & entry : sorts){ 249 | for (const string & constant : entry.second){ 250 | pout << " " << sanitise(shop_type_predicate_prefix) << sanitise(entry.first) << " " << sanitise(constant) << ")" << endl; 251 | } 252 | } 253 | 254 | pout << " )" << endl; 255 | pout << " ((" << sanitise("__top") << "))" << endl; 256 | pout << ")" << endl; 257 | 258 | } 259 | 260 | -------------------------------------------------------------------------------- /src/shopWriter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SHOPWRITER 2 | #define __SHOPWRITER 3 | 4 | #include "parsetree.hpp" 5 | 6 | void write_instance_as_SHOP(ostream & dout, ostream & pout); 7 | 8 | extern bool shop_1_compatability_mode; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/sortexpansion.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "parsetree.hpp" 6 | #include "domain.hpp" 7 | 8 | using namespace std; 9 | 10 | map > sort_adj; 11 | 12 | map sort_visi; 13 | 14 | void expansion_dfs(string sort){ 15 | if (sort_visi[sort] == 1) { 16 | cerr << "Sort hierarchy contains a cycle ... " << endl; 17 | exit(3); 18 | } 19 | 20 | sort_visi[sort] = 1; 21 | 22 | for(string subsort : sort_adj[sort]){ 23 | if (sort_visi[sort] != 2) expansion_dfs(subsort); // if not black 24 | // add constants to myself 25 | for (string subelem : sorts[subsort]) sorts[sort].insert(subelem); 26 | } 27 | sort_visi[sort] = 2; 28 | } 29 | 30 | void expand_sorts(){ 31 | for (auto def : sort_definitions){ 32 | if (def.has_parent_sort) sorts[def.parent_sort].size(); 33 | for (string subsort : def.declared_sorts){ 34 | sorts[subsort].size(); // touch to ensure it is contained in the map 35 | if (def.has_parent_sort) sort_adj[def.parent_sort].insert(subsort); 36 | } 37 | } 38 | 39 | for(auto s : sorts) expansion_dfs(s.first); 40 | } 41 | -------------------------------------------------------------------------------- /src/sortexpansion.hpp: -------------------------------------------------------------------------------- 1 | void expand_sorts(); 2 | 3 | -------------------------------------------------------------------------------- /src/typeof.cpp: -------------------------------------------------------------------------------- 1 | #include "typeof.hpp" 2 | #include "domain.hpp" 3 | #include "cwa.hpp" 4 | #include "parsetree.hpp" 5 | #include 6 | 7 | void create_typeof(){ 8 | // create a sort containing all objects 9 | for (auto s : sorts) for (string e : s.second) sorts["__object"].insert(e); 10 | 11 | // add instances to init 12 | for (auto s : sorts) for (string e : s.second){ 13 | ground_literal l; 14 | l.predicate = "typeOf"; 15 | l.positive = true; 16 | l.args.push_back(e); 17 | l.args.push_back(s.first); 18 | init.push_back(l); 19 | } 20 | 21 | set allSorts; 22 | for(auto s : sorts) allSorts.insert(s.first); 23 | sorts["Type"] = allSorts; 24 | 25 | predicate_definition typePred; 26 | typePred.name = "typeOf"; 27 | typePred.argument_sorts.push_back("__object"); 28 | typePred.argument_sorts.push_back("Type"); 29 | predicate_definitions.push_back(typePred); 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/typeof.hpp: -------------------------------------------------------------------------------- 1 | #include "cwa.hpp" 2 | 3 | void create_typeof(); 4 | -------------------------------------------------------------------------------- /src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | bool no_colors_in_output = false; 4 | 5 | string color(Color color, string text, Mode m, Color background){ 6 | if (no_colors_in_output) return text; 7 | return string () 8 | + "\033[" +std::to_string (m)+ ";" + std::to_string (30 + color) + "m" 9 | + ((background != COLOR_NONE)?("\033[" + std::to_string (40 + background) + "m"):"") 10 | + text 11 | + "\033[0;m" 12 | ; 13 | } 14 | -------------------------------------------------------------------------------- /src/util.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | enum Color{COLOR_GRAY,COLOR_RED,COLOR_GREEN,COLOR_YELLOW,COLOR_BLUE,COLOR_PURPLE,COLOR_CYAN,COLOR_WHITE,COLOR_NONE}; 6 | enum Mode{MODE_NORMAL,MODE_BOLD,MODE_CURSIVE,MODE_Y,MODE_UNDERLINE,MODE_BLINK}; 7 | 8 | string color (Color color, string text, Mode m = MODE_NORMAL, Color background = COLOR_NONE); 9 | 10 | extern bool no_colors_in_output; 11 | -------------------------------------------------------------------------------- /src/verification_encoding.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "verification_encoding.hpp" 5 | #include "cwa.hpp" 6 | #include "domain.hpp" 7 | 8 | void parseSolution(const string &planFile, vector &plan) { 9 | ifstream file(planFile); 10 | string line; 11 | while (getline(file, line)) { 12 | solution_step s; 13 | int endActionName = line.find("["); 14 | s.action_name = line.substr(0, endActionName); 15 | do { 16 | line = line.substr(endActionName + 1); 17 | endActionName = line.find(","); 18 | if (endActionName >= 0) { 19 | s.arguments.push_back(line.substr(0, endActionName)); 20 | } else { 21 | s.arguments.push_back(line.substr(0, line.length() - 1)); 22 | } 23 | } while (endActionName >= 0); 24 | plan.push_back(s); 25 | } 26 | } 27 | 28 | 29 | 30 | void encode_plan_verification(string & planFile){ 31 | vector plan; 32 | parseSolution(planFile, plan); 33 | 34 | // add new state features 35 | int first_pos_pred = predicate_definitions.size(); 36 | for (size_t i = 0; i < plan.size() + 1; i++) { 37 | predicate_definition pi; 38 | pi.name = "pref_pos_" + to_string(i); 39 | predicate_definitions.push_back(pi); 40 | } 41 | // unreachable state feature 42 | predicate_definition pUnreachable; 43 | pUnreachable.name = "f_unreachable"; 44 | predicate_definitions.push_back(pUnreachable); 45 | 46 | int objNr = 0; 47 | map argToType; 48 | unordered_map> newMethods; 49 | vector newAbstract; 50 | int orgActions = primitive_tasks.size(); 51 | 52 | for (size_t ai = 0; ai < plan.size(); ai++) { 53 | // find action from the plan 54 | task t = task_name_map.find(plan[ai].action_name)->second; 55 | // remove it from actions and store it so that it is added to abstract tasks later on 56 | // it is still in the mapping used before -> needed when an action is contained more than once 57 | auto iter = primitive_tasks.begin(); 58 | while (iter != primitive_tasks.end()){ 59 | if ((*iter).name == t.name) { 60 | break; 61 | } else { 62 | iter++; 63 | } 64 | } 65 | if (iter != primitive_tasks.end()) { // need to move from primitive to abstract tasks 66 | primitive_tasks.erase(iter); 67 | newAbstract.push_back(t); 68 | } 69 | 70 | // create copy of action 71 | task actionCopy; 72 | actionCopy.name = t.name + "|_plan_position_" + to_string(ai); 73 | actionCopy.number_of_original_vars = t.number_of_original_vars; 74 | 75 | for (size_t pi = 0; pi < plan[ai].arguments.size(); pi++) { 76 | string argName = plan[ai].arguments[pi]; 77 | if (argToType.find(argName) == argToType.end()) { 78 | // create subtype only containing that particular object 79 | string orgType = t.vars[pi].second; 80 | string newType = orgType + "_" + to_string(objNr++); 81 | argToType[argName] = newType; 82 | sorts[newType].insert(argName); 83 | } 84 | string var = t.vars[pi].first; 85 | actionCopy.vars.push_back(make_pair(var, argToType[argName])); // add argument with the newly created type 86 | } 87 | // no deep copy needed 88 | for (size_t i = 0; i < t.prec.size(); i++) { 89 | actionCopy.prec.push_back(t.prec[i]); 90 | } 91 | for (size_t i = 0; i < t.eff.size(); i++) { 92 | actionCopy.eff.push_back(t.eff[i]); 93 | } 94 | for (size_t i = 0; i < t.ceff.size(); i++) { 95 | actionCopy.ceff.push_back(t.ceff[i]); 96 | } 97 | for (size_t i = 0; i < t.constraints.size(); i++) { 98 | actionCopy.constraints.push_back(t.constraints[i]); 99 | } 100 | for (size_t i = 0; i < t.costExpression.size(); i++) { 101 | actionCopy.costExpression.push_back(t.costExpression[i]); 102 | } 103 | actionCopy.artificial = true; 104 | 105 | // add new preconditions and effects to position the new action in the plan 106 | literal lPrec; 107 | lPrec.positive = true; 108 | lPrec.predicate = predicate_definitions[first_pos_pred + ai].name; 109 | actionCopy.prec.push_back(lPrec); 110 | 111 | literal lAdd; 112 | lAdd.positive = true; 113 | lAdd.predicate = predicate_definitions[first_pos_pred + ai + 1].name; 114 | actionCopy.eff.push_back(lAdd); 115 | 116 | literal lDel; 117 | lDel.positive = false; 118 | lDel.predicate = predicate_definitions[first_pos_pred + ai].name; 119 | actionCopy.eff.push_back(lDel); 120 | 121 | primitive_tasks.push_back(actionCopy); 122 | 123 | // create a new method decomposing the new abstract task into the new action 124 | method m; 125 | m.name = "_!m_prefix_" + to_string(ai); 126 | plan_step ps; 127 | ps.id = "task1"; 128 | ps.task = actionCopy.name; 129 | for (size_t i = 0; i < actionCopy.vars.size(); i++) { 130 | m.vars.push_back(actionCopy.vars[i]); 131 | m.atargs.push_back(actionCopy.vars[i].first); 132 | ps.args.push_back(actionCopy.vars[i].first); 133 | } 134 | m.ps.push_back(ps); 135 | m.at = t.name; 136 | methods.push_back(m); 137 | } 138 | // now we move that tasks that had former been actions to the abstract tasks 139 | for (task t : newAbstract) { 140 | t.prec.clear(); 141 | t.eff.clear(); 142 | t.ceff.clear(); 143 | abstract_tasks.push_back(t); 144 | } 145 | 146 | // all original actions not contained in the plan to verify get a new predicate that make them unreachable 147 | for (size_t i = 0; i < (orgActions - newAbstract.size()); i++) { 148 | literal l; 149 | l.predicate = pUnreachable.name; 150 | l.positive = true; 151 | primitive_tasks[i].prec.push_back(l); 152 | } 153 | 154 | // the name-to-task-mapping is invalid, we renew it 155 | task_name_map.clear(); 156 | for(task t : abstract_tasks) { 157 | task_name_map[t.name] = t; 158 | } 159 | for(task t : primitive_tasks) { 160 | task_name_map[t.name] = t; 161 | } 162 | 163 | // add initial fact to make the first action applicable 164 | ground_literal lInit; 165 | lInit.positive = true; 166 | lInit.predicate = predicate_definitions[first_pos_pred].name; 167 | init.push_back(lInit); 168 | 169 | // add a new goal fact enforcing all actions from the verified solution to be contained in the new solution 170 | ground_literal lGoal; 171 | lGoal.positive = true; 172 | lGoal.predicate = predicate_definitions[predicate_definitions.size() - 2].name; 173 | goal.push_back(lGoal); 174 | } 175 | -------------------------------------------------------------------------------- /src/verification_encoding.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __VERIFY_ENCODING 2 | #define __VERIFY_ENCODING 3 | 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | struct solution_step{ 9 | string action_name; 10 | vector arguments; 11 | }; 12 | 13 | void parseSolution(const string &planFile, vector &plan); 14 | void encode_plan_verification(string & planFile); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/verify.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __VERIFY 2 | #define __VERIFY 3 | 4 | #include "parsetree.hpp" 5 | 6 | bool verify_plan(istream & plan, bool use_order_information, bool lenient_mode, int verbose_output); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /tests/conditional-effect-problem.hddl: -------------------------------------------------------------------------------- 1 | (define 2 | (problem p1) 3 | (:domain test-domain) 4 | (:objects 5 | ) 6 | (:htn 7 | :parameters (?x - object) 8 | :subtasks (and 9 | (task0 (t1 ?x)) 10 | ) 11 | ) 12 | (:init 13 | (p c) 14 | ) 15 | 16 | (:goal 17 | (r c) 18 | ) 19 | ) 20 | -------------------------------------------------------------------------------- /tests/conditional-effect.hddl: -------------------------------------------------------------------------------- 1 | (define (domain test-domain) 2 | (:requirements :typing :hierachie) 3 | (:types 4 | object 5 | ) 6 | (:predicates 7 | (p ?x - object) 8 | (q ?x - object) 9 | (r ?x - object) 10 | ) 11 | 12 | (:constants c - object) 13 | 14 | (:task t1 :parameters (?a - object)) 15 | 16 | (:method method0 17 | :parameters (?x - object) 18 | :task (t1 ?x) 19 | :subtasks (and 20 | (task0 (prim ?x)) 21 | (task1 (prim ?x)) 22 | (task2 (prim ?x)) 23 | ) 24 | ) 25 | 26 | (:action prim 27 | :parameters (?x - object) 28 | :precondition 29 | (and 30 | ) 31 | :effect 32 | (and 33 | (when (p ?x) (and (q ?x) (not (p ?x)))) 34 | (when (not (p ?x)) (not (q ?x))) 35 | 36 | (when (not (p ?x)) (when (q ?x) (r ?x))) 37 | ) 38 | ) 39 | ) 40 | -------------------------------------------------------------------------------- /tests/conditional-effect.htn: -------------------------------------------------------------------------------- 1 | #number_constants_number_sorts 2 | 1 1 3 | #constants 4 | c 5 | #end_constants 6 | #sorts_each_with_number_of_members_and_members 7 | object 1 0 8 | #end_sorts 9 | #number_of_predicates 10 | 4 11 | #predicates_each_with_number_of_arguments_and_argument_sorts 12 | +p 1 0 13 | -p 1 0 14 | +q 1 0 15 | +r 1 0 16 | #end_predicates 17 | #number_of_functions 18 | 0 19 | #function_declarations_with_number_of_arguments_and_argument_sorts 20 | #number_primitive_tasks_and_number_abstract_tasks 21 | 1 2 22 | #begin_task_name_number_of_original_variables_and_number_of_variables 23 | prim 1 1 24 | #sorts_of_variables 25 | 0 26 | #end_variables 27 | #number_of_cost_statements 28 | 1 29 | #begin_cost_statements 30 | const 1 31 | #end_cost_statements 32 | #preconditions_each_predicate_and_argument_variables 33 | 0 34 | #add_each_predicate_and_argument_variables 35 | 0 36 | #conditional_add_each_with_conditions_and_effect 37 | 3 38 | 1 0 0 2 0 39 | 1 0 0 1 0 40 | 2 2 0 1 0 3 0 41 | #del_each_predicate_and_argument_variables 42 | 0 43 | #conditional_del_each_with_conditions_and_effect 44 | 2 45 | 1 0 0 1 0 46 | 1 1 0 0 0 47 | #variable_constraints_first_number_then_individual_constraints 48 | 0 49 | #end_of_task 50 | #begin_task_name_number_of_original_variables_and_number_of_variables 51 | t1 1 1 52 | #sorts_of_variables 53 | 0 54 | #end_variables 55 | #end_of_task 56 | #begin_task_name_number_of_original_variables_and_number_of_variables 57 | __top 0 0 58 | #sorts_of_variables 59 | 60 | #end_variables 61 | #end_of_task 62 | #number_of_methods 63 | 2 64 | #begin_method_name_abstract_task_number_of_variables 65 | __top_method 2 1 66 | #variable_sorts 67 | 0 68 | #parameter_of_abstract_task 69 | 70 | #number_of_subtasks 71 | 1 72 | #subtasks_each_with_task_id_and_parameter_variables 73 | 1 0 74 | #number_of_ordering_constraints_and_ordering 75 | 0 76 | #variable_constraints 77 | 0 78 | #end_of_method 79 | #begin_method_name_abstract_task_number_of_variables 80 | method0 1 1 81 | #variable_sorts 82 | 0 83 | #parameter_of_abstract_task 84 | 0 85 | #number_of_subtasks 86 | 3 87 | #subtasks_each_with_task_id_and_parameter_variables 88 | 0 0 89 | 0 0 90 | 0 0 91 | #number_of_ordering_constraints_and_ordering 92 | 0 93 | #variable_constraints 94 | 0 95 | #end_of_method 96 | #init_and_goal_facts 97 | 1 1 98 | 0 0 99 | #end_init 100 | 3 0 101 | #end_goal 102 | #init_function_facts 103 | 0 104 | #initial_task 105 | 2 106 | -------------------------------------------------------------------------------- /tests/conditional-test-problem.hddl: -------------------------------------------------------------------------------- 1 | (define 2 | (problem p1) 3 | (:domain test-domain) 4 | (:objects 5 | ) 6 | (:htn 7 | :parameters (?x ?y - object) 8 | :subtasks (and 9 | (task0 (t1 ?x ?y)) 10 | ) 11 | ) 12 | (:init 13 | ) 14 | ) 15 | -------------------------------------------------------------------------------- /tests/conditional-test.hddl: -------------------------------------------------------------------------------- 1 | (define (domain test-domain) 2 | (:requirements :typing :hierachie) 3 | (:types 4 | object 5 | ) 6 | (:predicates 7 | (p ?arg0 - object ?arg1 - object) 8 | (q ?arg0 - object) 9 | ) 10 | 11 | (:constants c d - object) 12 | 13 | (:task t1 :parameters (?a ?b - object)) 14 | 15 | (:method method0 16 | :parameters (?x - object) 17 | :task (t1 d ?x) 18 | :subtasks (and 19 | (task0 (prim ?x)) 20 | ) 21 | ) 22 | 23 | (:action prim 24 | :parameters (?x - object) 25 | :precondition 26 | (and 27 | (forall (?x ?y - object) (or (p ?x ?y) (q ?x))) 28 | ) 29 | :effect 30 | (and 31 | ) 32 | ) 33 | ) 34 | -------------------------------------------------------------------------------- /tests/constant-in-method-test-problem.hddl: -------------------------------------------------------------------------------- 1 | (define 2 | (problem p1) 3 | (:domain test-domain) 4 | (:objects 5 | ) 6 | (:htn 7 | :parameters (?x ?y - object) 8 | :subtasks (and 9 | (task0 (t1 ?x ?y)) 10 | ) 11 | ) 12 | (:init 13 | ) 14 | ) 15 | -------------------------------------------------------------------------------- /tests/constant-in-method-test.hddl: -------------------------------------------------------------------------------- 1 | (define (domain test-domain) 2 | (:requirements :typing :hierachie) 3 | (:types 4 | object 5 | ) 6 | (:predicates 7 | (p ?arg0 - object ?arg1 - object) 8 | (q ?arg0 - object) 9 | ) 10 | 11 | (:constants c d e - object) 12 | 13 | (:task t1 :parameters (?a ?b - object)) 14 | 15 | (:method method0 16 | :parameters (?x - object) 17 | :task (t1 d ?x) 18 | :subtasks (and 19 | (task0 (prim ?x)) 20 | ) 21 | ) 22 | 23 | (:action prim 24 | :parameters (?x - object) 25 | :precondition 26 | (and 27 | (forall (?x - object) (or (p ?x ?x) (q ?x))) 28 | ) 29 | :effect 30 | (and 31 | ) 32 | ) 33 | ) 34 | -------------------------------------------------------------------------------- /tests/effect-precedence-problem.hddl: -------------------------------------------------------------------------------- 1 | (define 2 | (problem p1) 3 | (:domain test-domain) 4 | (:objects 5 | ) 6 | (:htn 7 | :parameters (?x - object) 8 | :subtasks (and 9 | (task0 (t1 ?x)) 10 | ) 11 | ) 12 | (:init 13 | ) 14 | ) 15 | -------------------------------------------------------------------------------- /tests/effect-precedence.hddl: -------------------------------------------------------------------------------- 1 | (define (domain test-domain) 2 | (:requirements :typing :hierachie) 3 | (:types 4 | object 5 | ) 6 | (:predicates 7 | (q ?arg0 - object) 8 | ) 9 | 10 | (:constants c d - object) 11 | 12 | (:task t1 :parameters (?a - object)) 13 | 14 | (:method method0 15 | :parameters (?x - object) 16 | :task (t1 ?x) 17 | :subtasks (and 18 | (task0 (prim1 ?x)) 19 | (task1 (prim2 c)) 20 | ) 21 | ) 22 | 23 | (:action prim1 24 | :parameters (?x - object) 25 | :precondition 26 | (and 27 | 28 | ) 29 | :effect 30 | (and 31 | (not (q ?x)) 32 | (q c) 33 | ) 34 | ) 35 | (:action prim2 36 | :parameters (?x - object) 37 | :precondition 38 | (and 39 | (not (q ?x)) 40 | ) 41 | :effect 42 | (and 43 | ) 44 | ) 45 | ) 46 | -------------------------------------------------------------------------------- /tests/empty-d.hddl: -------------------------------------------------------------------------------- 1 | (define (domain test-domain) 2 | (:requirements :typing :hierachie) 3 | 4 | (:task task1 :parameters ()) 5 | 6 | (:method donothing 7 | :parameters () 8 | :task (task1) 9 | :subtasks (and 10 | ) 11 | ) 12 | ) 13 | -------------------------------------------------------------------------------- /tests/empty-p.hddl: -------------------------------------------------------------------------------- 1 | (define 2 | (problem p1) 3 | (:domain test-domain) 4 | (:objects 5 | ) 6 | (:htn 7 | :parameters () 8 | :subtasks (and 9 | (task0 (task1)) 10 | ) 11 | ) 12 | (:init 13 | ) 14 | ) 15 | -------------------------------------------------------------------------------- /tests/empty.plan: -------------------------------------------------------------------------------- 1 | ==> 2 | root 0 3 | 0 task1 -> donothing 4 | <== 5 | 6 | 7 | -------------------------------------------------------------------------------- /tests/entertainment-01.plan: -------------------------------------------------------------------------------- 1 | SAT solver = 10 2 | SAT solver for K=0003 = 0 3 | SAT solver for K=0004 = 10 4 | 5 | #1 "40 sat:90:solved"="true";"30 problem:05:number of primitive actions"="35";"30 problem:01:number of constants"="0";"30 problem:04:number of abstract actions"="20";"02 properties:04:tail recursive"="true";"00 global:80:peak memory"="115660664";"40 sat:20:state formula"="7739";"40 sat:01:number of variables"="4899";"40 sat:14:K offset"="0";"40 sat:30:number of paths"="12";"40 sat:00:plan length"="-1";"40 sat:50:number of ordering clauses"="5571";"02 properties:02:mostly acyclic"="true";"30 problem:06:number of methods"="46";"30 problem:07:number of primitive shop actions"="26";"02 properties:05:totally ordered"="true";"02 properties:06:last task in all methods"="true";"30 problem:03:number of actions"="55";"30 problem:08:number of primitive non-shop actions"="9";"30 problem:02:number of predicates"="20";"40 sat:03:number of horn"="7762";"40 sat:15:K chosen value"="4";"30 problem:10:average method size"="1";"02 properties:03:regular"="false";"30 problem:09:size of largest method"="5";"40 sat:03:average size of clauses"="2.656909462219197";"40 sat:02:number of clauses"="8814";"40 sat:50:number of state clauses"="2168";"40 sat:03:number of assert"="11";"40 sat:22:method children clauses"="0";"00 global:90:planner result"="SOLUTION";"02 properties:01:acyclic"="true";"40 sat:50:number of decomposition clauses"="1075";"00 global:02:randomseed"="42";"40 sat:91:timeout"="false";"01 parsing:01:file parser"="752";"01 parsing:08:flatten formula"="394";"40 sat:41:SAT solver for K=0004"="10";"40 sat:00:total"="457";"40 sat:16:generate state formula"="336";"40 sat:20:transform to DIMACS"="34";"40 sat:11:generate path decomposition tree"="136";"02 preprocessing:07:compile methods with identical tasks"="4";"01 parsing:07:strip domain of hybridity"="3";"02 preprocessing:08:removing unnecessary predicates"="113";"01 parsing:03:closed world assumption"="125";"02 preprocessing:11:lifted reachabiltiy analysis"="75";"01 parsing:02:sort expansion"="355";"40 sat:12:normalise path decomposition tree"="24";"40 sat:40:SAT solver"="10";"01 parsing:00:total"="1777";"40 sat:10:generate formula"="340";"01 parsing:04:inherit preconditions"="0";"02 preprocessing:01:compile negative preconditions"="51";"00 total:00:total"="4686";"40 sat:13:sog optimisation"="37";"02 preprocessing:12:grounded planning graph analysis"="563";"02 preprocessing:02:compile unit methods"="0";"02 preprocessing:23:grounded task decomposition graph analysis"="544";"02 preprocessing:04:split parameter"="36";"01 parsing:05:shop methods"="42";"01 parsing:06:eliminate identical variables"="105";"40 sat:15:translate path decomposition tree to clauses"="132";"02 preprocessing:05:expand choiceless abstract tasks"="206";"40 sat:41:SAT solver for K=0003"="0";"02 preprocessing:00:total"="1738";"02 preprocessing:99:create artificial top task"="4";"02 preprocessing:84:grounding"="119" 6 | ==> 7 | 0 plug dvd-1 dvd-1-scart-1 scart-to-cinch-1 scart-to-cinch-1-scart-1 8 | 1 plug scart-to-cinch-1 scart-to-cinch-1-cinch-3 cinch-cable-2 cinch-cable-2-cinch-1 9 | 2 plug cinch-cable-2 cinch-cable-2-cinch-2 simple-tv-1 simple-tv-1-cinch-1 10 | 3 plug scart-to-cinch-1 scart-to-cinch-1-cinch-2 cinch-cable-1 cinch-cable-1-cinch-1 11 | 4 plug cinch-cable-1 cinch-cable-1-cinch-2 simple-tv-1 simple-tv-1-cinch-2 12 | root 6 13 | 5 av_connect dvd-1 simple-tv-1 -> m-connect-split-1 8 12 14 | 6 __choicelessATCompilation__top_1 -> __top_1 5 15 | 7 direct_a_connect dvd-1 scart-to-cinch-1 -> m-dconnect-a-empty 16 | 8 v_connect dvd-1 simple-tv-1 -> <;v_connect[dvd-1,scart-to-cinch-1];m-connect-direct-v;0;-1,1,2> 14 10 13 17 | 9 direct_a_connect scart-to-cinch-1 cinch-cable-1 -> <<;plug__CONSEQUENT__[scart-to-cinch-1,scart-to-cinch-1-cinch-2,cinch-cable-1,cinch-cable-1-cinch-1];_M-plug__CONSEQUENT____ANTECEDENT;0;-1>;plug__CONSEQUENT____ANTECEDENT[scart-to-cinch-1,scart-to-cinch-1-cinch-2,cinch-cable-1,cinch-cable-1-cinch-1];_M-plug__CONSEQUENT____ANTECEDENT__DISJUNCT-0;0;-1> 3 18 | 10 direct_v_connect scart-to-cinch-1 cinch-cable-2 -> <<;plug__ANTECEDENT[scart-to-cinch-1,scart-to-cinch-1-cinch-3,cinch-cable-2,cinch-cable-2-cinch-1];_M-plug__ANTECEDENT__DISJUNCT-0;0;-1>;plug__ANTECEDENT__DISJUNCT-0[scart-to-cinch-1,scart-to-cinch-1-cinch-3,cinch-cable-2,cinch-cable-2-cinch-1];_M-plug__ANTECEDENT__DISJUNCT-0__CONSEQUENT__;0;-1> 1 19 | 11 direct_a_connect cinch-cable-1 simple-tv-1 -> <<;plug__CONSEQUENT__[cinch-cable-1,cinch-cable-1-cinch-2,simple-tv-1,simple-tv-1-cinch-2];_M-plug__CONSEQUENT____ANTECEDENT;0;-1>;plug__CONSEQUENT____ANTECEDENT[cinch-cable-1,cinch-cable-1-cinch-2,simple-tv-1,simple-tv-1-cinch-2];_M-plug__CONSEQUENT____ANTECEDENT__DISJUNCT-1;0;-1> 4 20 | 12 a_connect dvd-1 simple-tv-1 -> <;a_connect[dvd-1,scart-to-cinch-1];m-connect-direct-a;0;-1,1,2> 7 9 11 21 | 13 direct_v_connect cinch-cable-2 simple-tv-1 -> <<;plug__ANTECEDENT[cinch-cable-2,cinch-cable-2-cinch-2,simple-tv-1,simple-tv-1-cinch-1];_M-plug__ANTECEDENT__DISJUNCT-1;0;-1>;plug__ANTECEDENT__DISJUNCT-1[cinch-cable-2,cinch-cable-2-cinch-2,simple-tv-1,simple-tv-1-cinch-1];_M-plug__ANTECEDENT__DISJUNCT-1__CONSEQUENT__;0;-1> 2 22 | 14 direct_v_connect dvd-1 scart-to-cinch-1 -> <;plug__CONSEQUENT__[dvd-1,dvd-1-scart-1,scart-to-cinch-1,scart-to-cinch-1-scart-1];_M-plug__CONSEQUENT____CONSEQUENT__;0;-1> 0 23 | -------------------------------------------------------------------------------- /tests/interleaving-d.hddl: -------------------------------------------------------------------------------- 1 | (define (domain test-domain) 2 | (:requirements :typing :hierachie) 3 | (:predicates 4 | (p) 5 | (q) 6 | (r) 7 | ) 8 | 9 | (:task t1) 10 | (:task t2) 11 | 12 | (:method method0 13 | :task (t1) 14 | :ordered-subtasks (and 15 | (A) 16 | (C) 17 | ) 18 | ) 19 | 20 | (:method method1 21 | :task (t2) 22 | :ordered-subtasks (and 23 | (B) 24 | (D) 25 | ) 26 | ) 27 | 28 | (:action A :precondition (and) :effect (and (p))) 29 | (:action B :precondition (and (p)) :effect (and (q))) 30 | (:action C :precondition (and (q)) :effect (and (r))) 31 | (:action D :precondition (and (q)) :effect (and )) 32 | ) 33 | -------------------------------------------------------------------------------- /tests/interleaving-p.hddl: -------------------------------------------------------------------------------- 1 | (define 2 | (problem p1) 3 | (:domain test-domain) 4 | (:objects 5 | ) 6 | (:htn 7 | :subtasks (and 8 | (t1) (t2) 9 | ) 10 | ) 11 | (:init 12 | ) 13 | ) 14 | -------------------------------------------------------------------------------- /tests/method-effect-problem.hddl: -------------------------------------------------------------------------------- 1 | (define 2 | (problem p1) 3 | (:domain test-domain) 4 | (:objects 5 | ) 6 | (:htn 7 | :parameters (?x - object) 8 | :subtasks (and 9 | (task0 (t1 ?x)) 10 | ) 11 | ) 12 | (:init 13 | (p c) 14 | ) 15 | 16 | (:goal 17 | (r c) 18 | ) 19 | ) 20 | -------------------------------------------------------------------------------- /tests/method-effect.hddl: -------------------------------------------------------------------------------- 1 | (define (domain test-domain) 2 | (:requirements :typing :hierachie) 3 | (:types 4 | object 5 | ) 6 | (:predicates 7 | (p ?x - object) 8 | (q ?x - object) 9 | (r ?x - object) 10 | ) 11 | 12 | (:constants c - object) 13 | 14 | (:task t1 :parameters (?a - object)) 15 | (:task t2 :parameters (?a - object)) 16 | 17 | (:method method0 18 | :parameters (?x - object) 19 | :task (t1 ?x) 20 | :subtasks (and 21 | (task0 (t2 ?x)) 22 | (task1 (t2 ?x)) 23 | (task2 (t2 ?x)) 24 | ) 25 | ) 26 | 27 | (:method method1 28 | :parameters (?x - object) 29 | :task (t2 ?x) 30 | :precondition 31 | (and 32 | ) 33 | :effect 34 | (and 35 | (when (p ?x) (and (q ?x) (not (p ?x)))) 36 | (when (not (p ?x)) (not (q ?x))) 37 | 38 | (when (not (p ?x)) (when (q ?x) (r ?x))) 39 | ) 40 | ) 41 | ) 42 | -------------------------------------------------------------------------------- /tests/minecraft-costs-constant.hddl: -------------------------------------------------------------------------------- 1 | (define (domain minecraft) 2 | (:requirements :typing) 3 | 4 | (:types 5 | location blocktype direction numbers - object 6 | 7 | ) 8 | 9 | (:predicates 10 | (empty ?location - location) 11 | (blockat ?location - location ?t - blocktype) 12 | (neighbour ?loc1 ?loc2 - location ?dir - direction) 13 | (on-top ?loc1 ?loc2 - location) 14 | (isone ?z - numbers) 15 | (prev ?z ?z2 - numbers) 16 | ) 17 | 18 | (:functions 19 | (total-cost) - number 20 | (block-cost ?b - blocktype) - number 21 | ) 22 | 23 | (:task buildhouse :parameters (?loc1 ?loc2 ?loc3 ?loc4 ?loc5 ?loc6 - location ?len ?len2 ?hgt - numbers ?t - blocktype)) 24 | (:task buildwall :parameters (?loc1 - location ?len ?hgt - numbers ?d - direction ?t - blocktype)) 25 | (:task buildroof :parameters (?loc1 - location ?len ?wdt - numbers ?d ?d2 - direction ?t - blocktype)) 26 | (:task builddoor :parameters (?loc1 - location)) 27 | (:task buildrow :parameters (?loc1 - location ?len - numbers ?d - direction ?t - blocktype)) 28 | (:task placeblockabstract :parameters (?loc1 - location ?t - blocktype)) 29 | (:task removeblockabstract :parameters (?loc1 - location)) 30 | 31 | 32 | (:method build-house-1 33 | :parameters (?loc1 ?loc2 ?loc3 ?loc4 ?loc5 ?loc6 - location ?len ?len2 ?hgt - numbers ?t - blocktype) 34 | :task (buildhouse ?loc1 ?loc2 ?loc3 ?loc4 ?loc5 ?loc6 ?len ?len2 ?hgt ?t) 35 | :precondition () 36 | :ordered-subtasks (and 37 | (buildwall ?loc1 ?len ?hgt e ?t) 38 | (buildwall ?loc2 ?len2 ?hgt n ?t) 39 | (buildwall ?loc3 ?len ?hgt w ?t) 40 | (buildwall ?loc4 ?len2 ?hgt s ?t) 41 | (builddoor ?loc5) 42 | (buildroof ?loc6 ?len ?len2 e n ?t) 43 | 44 | ) 45 | ) 46 | 47 | (:method build-wall-1 48 | :parameters (?loc1 - location ?len ?hgt - numbers ?d - direction ?t - blocktype) 49 | :task (buildwall ?loc1 ?len ?hgt ?d ?t) 50 | :precondition (and (isone ?hgt) ) 51 | :subtasks (and 52 | (buildrow ?loc1 ?len ?d ?t) 53 | ) 54 | ) 55 | 56 | (:method build-wall-2 57 | :parameters (?loc1 ?loc2 - location ?len ?hgt ?hgt2 - numbers ?d - direction ?t - blocktype) 58 | :task (buildwall ?loc1 ?len ?hgt ?d ?t) 59 | :precondition (and (not(isone ?hgt)) (prev ?hgt ?hgt2) (on-top ?loc1 ?loc2) ) 60 | :ordered-subtasks (and 61 | (buildrow ?loc1 ?len ?d ?t) 62 | (buildwall ?loc2 ?len ?hgt2 ?d ?t) 63 | ) 64 | ) 65 | 66 | (:method build-roof-1 67 | :parameters (?loc1 - location ?len ?wdt - numbers ?d ?d2 - direction ?t - blocktype) 68 | :task (buildroof ?loc1 ?len ?wdt ?d ?d2 ?t) 69 | :precondition (and (isone ?wdt) ) 70 | :subtasks (and 71 | (buildrow ?loc1 ?len ?d ?t) 72 | ) 73 | ) 74 | 75 | (:method build-roof-2 76 | :parameters (?loc1 ?loc2 - location ?len ?wdt ?wdt2 - numbers ?d ?d2 - direction ?t - blocktype) 77 | :task (buildroof ?loc1 ?len ?wdt ?d ?d2 ?t) 78 | :precondition (and (not(isone ?wdt)) (prev ?wdt ?wdt2) (neighbour ?loc1 ?loc2 ?d2) ) 79 | :ordered-subtasks (and 80 | (buildrow ?loc1 ?len ?d ?t) 81 | (buildroof ?loc2 ?len ?wdt2 ?d ?d2 ?t) 82 | ) 83 | ) 84 | 85 | (:method build-door-1 86 | :parameters (?loc1 ?loc2 - location) 87 | :task (builddoor ?loc1) 88 | :precondition (and (on-top ?loc1 ?loc2)) 89 | :ordered-subtasks (and 90 | (removeblockabstract ?loc1) 91 | (removeblockabstract ?loc2) 92 | ) 93 | ) 94 | 95 | 96 | (:method build-row-1 97 | :parameters (?loc1 - location ?len - numbers ?d - direction ?t - blocktype) 98 | :task (buildrow ?loc1 ?len ?d ?t) 99 | :precondition (and (isone ?len) ) 100 | :subtasks (and 101 | (placeblockabstract ?loc1 ?t) 102 | ) 103 | ) 104 | 105 | (:method build-row-2 106 | :parameters (?loc1 ?loc2 - location ?len ?len2 - numbers ?d - direction ?t - blocktype) 107 | :task (buildrow ?loc1 ?len ?d ?t) 108 | :precondition (and (not(isone ?len)) (prev ?len ?len2) (neighbour ?loc1 ?loc2 ?d) ) 109 | :ordered-subtasks (and 110 | (placeblockabstract ?loc1 ?t) 111 | (buildrow ?loc2 ?len2 ?d ?t) 112 | ) 113 | ) 114 | 115 | (:method build-row-3 116 | :parameters (?loc1 ?loc2 - location ?len ?len2 - numbers ?d - direction ?t - blocktype) 117 | :task (buildrow ?loc1 ?len ?d ?t) 118 | :precondition (and (not(isone ?len)) (prev ?len ?len2) (neighbour ?loc1 ?loc2 ?d) ) 119 | :ordered-subtasks (and 120 | (buildrow ?loc2 ?len2 ?d ?t) 121 | (placeblockabstract ?loc1 ?t) 122 | ) 123 | ) 124 | 125 | (:method place-block-abstract-1 126 | :parameters (?loc1 - location ?t - blocktype) 127 | :task (placeblockabstract ?loc1 ?t) 128 | :precondition (and (empty ?loc1)) 129 | :subtasks (and 130 | (placeblock ?loc1 ?t) 131 | ) 132 | ) 133 | 134 | (:method place-block-abstract-2 135 | :parameters (?loc1 - location ?t - blocktype) 136 | :task (placeblockabstract ?loc1 ?t) 137 | :precondition (and (blockat ?loc1 ?t)) 138 | :subtasks () 139 | ) 140 | 141 | (:method place-block-abstract-3 142 | :parameters (?loc1 - location ?t ?t2 - blocktype) 143 | :task (placeblockabstract ?loc1 ?t) 144 | :precondition (and (blockat ?loc1 ?t2) ) 145 | :ordered-subtasks (and 146 | (removeblock ?loc1 ?t2) 147 | (placeblock ?loc1 ?t) 148 | ) 149 | ) 150 | 151 | (:method remove-block-abstract-1 152 | :parameters (?loc1 - location) 153 | :task (removeblockabstract ?loc1) 154 | :precondition (and (empty ?loc1)) 155 | :subtasks () 156 | ) 157 | 158 | (:method remove-block-abstract-2 159 | :parameters (?loc1 - location ?t - blocktype) 160 | :task (removeblockabstract ?loc1) 161 | :precondition (and (blockat ?loc1 ?t)) 162 | :subtasks (and 163 | (removeblock ?loc1 ?t) 164 | ) 165 | ) 166 | 167 | 168 | (:action placeblock 169 | :parameters (?location - location ?t - blocktype) 170 | :precondition (and (empty ?location) ) 171 | :effect (and 172 | (increase (total-cost) 1) 173 | (not (empty ?location)) (blockat ?location ?t)) ) 174 | 175 | (:action removeblock 176 | :parameters (?location - location ?t - blocktype) 177 | :precondition (and (not(empty ?location)) ) 178 | :effect (and 179 | (increase (total-cost) 5) 180 | (empty ?location) (not(blockat ?location ?t))) ) 181 | 182 | ) 183 | -------------------------------------------------------------------------------- /tests/minecraft-costs-problem.hddl: -------------------------------------------------------------------------------- 1 | (define (problem house) 2 | (:domain minecraft) 3 | (:objects 4 | l-0-0-0 l-0-0-1 l-0-0-2 l-0-0-3 5 | l-0-1-0 l-0-1-1 l-0-1-2 l-0-1-3 6 | l-0-2-0 l-0-2-1 l-0-2-2 l-0-2-3 7 | l-0-3-0 l-0-3-1 l-0-3-2 l-0-3-3 8 | l-1-0-0 l-1-0-1 l-1-0-2 l-1-0-3 9 | l-1-1-0 l-1-1-1 l-1-1-2 l-1-1-3 10 | l-1-2-0 l-1-2-1 l-1-2-2 l-1-2-3 11 | l-1-3-0 l-1-3-1 l-1-3-2 l-1-3-3 12 | l-2-0-0 l-2-0-1 l-2-0-2 l-2-0-3 13 | l-2-1-0 l-2-1-1 l-2-1-2 l-2-1-3 14 | l-2-2-0 l-2-2-1 l-2-2-2 l-2-2-3 15 | l-2-3-0 l-2-3-1 l-2-3-2 l-2-3-3 16 | l-3-0-0 l-3-0-1 l-3-0-2 l-3-0-3 17 | l-3-1-0 l-3-1-1 l-3-1-2 l-3-1-3 18 | l-3-2-0 l-3-2-1 l-3-2-2 l-3-2-3 19 | l-3-3-0 l-3-3-1 l-3-3-2 l-3-3-3 20 | l-4-0-0 l-4-0-1 l-4-0-2 l-4-0-3 21 | l-4-1-0 l-4-1-1 l-4-1-2 l-4-1-3 22 | l-4-2-0 l-4-2-1 l-4-2-2 l-4-2-3 23 | l-4-3-0 l-4-3-1 l-4-3-2 l-4-3-3 24 | - location 25 | e w s n 26 | - direction 27 | wood stone earth 28 | - blocktype 29 | n0 n1 n2 n3 30 | - numbers 31 | ) 32 | (:htn :parameters () 33 | :ordered-subtasks (and (buildhouse l-1-0-0 l-1-0-2 l-1-2-2 l-1-2-0 l-1-1-0 l-4-0-0 n3 n3 n3 stone)) )(:init 34 | 35 | (neighbour l-0-0-0 l-0-0-1 e) (neighbour l-0-0-1 l-0-0-2 e) (neighbour l-0-0-2 l-0-0-3 e) 36 | (neighbour l-0-1-0 l-0-1-1 e) (neighbour l-0-1-1 l-0-1-2 e) (neighbour l-0-1-2 l-0-1-3 e) 37 | (neighbour l-0-2-0 l-0-2-1 e) (neighbour l-0-2-1 l-0-2-2 e) (neighbour l-0-2-2 l-0-2-3 e) 38 | (neighbour l-0-3-0 l-0-3-1 e) (neighbour l-0-3-1 l-0-3-2 e) (neighbour l-0-3-2 l-0-3-3 e) 39 | (neighbour l-1-0-0 l-1-0-1 e) (neighbour l-1-0-1 l-1-0-2 e) (neighbour l-1-0-2 l-1-0-3 e) 40 | (neighbour l-1-1-0 l-1-1-1 e) (neighbour l-1-1-1 l-1-1-2 e) (neighbour l-1-1-2 l-1-1-3 e) 41 | (neighbour l-1-2-0 l-1-2-1 e) (neighbour l-1-2-1 l-1-2-2 e) (neighbour l-1-2-2 l-1-2-3 e) 42 | (neighbour l-1-3-0 l-1-3-1 e) (neighbour l-1-3-1 l-1-3-2 e) (neighbour l-1-3-2 l-1-3-3 e) 43 | (neighbour l-2-0-0 l-2-0-1 e) (neighbour l-2-0-1 l-2-0-2 e) (neighbour l-2-0-2 l-2-0-3 e) 44 | (neighbour l-2-1-0 l-2-1-1 e) (neighbour l-2-1-1 l-2-1-2 e) (neighbour l-2-1-2 l-2-1-3 e) 45 | (neighbour l-2-2-0 l-2-2-1 e) (neighbour l-2-2-1 l-2-2-2 e) (neighbour l-2-2-2 l-2-2-3 e) 46 | (neighbour l-2-3-0 l-2-3-1 e) (neighbour l-2-3-1 l-2-3-2 e) (neighbour l-2-3-2 l-2-3-3 e) 47 | (neighbour l-3-0-0 l-3-0-1 e) (neighbour l-3-0-1 l-3-0-2 e) (neighbour l-3-0-2 l-3-0-3 e) 48 | (neighbour l-3-1-0 l-3-1-1 e) (neighbour l-3-1-1 l-3-1-2 e) (neighbour l-3-1-2 l-3-1-3 e) 49 | (neighbour l-3-2-0 l-3-2-1 e) (neighbour l-3-2-1 l-3-2-2 e) (neighbour l-3-2-2 l-3-2-3 e) 50 | (neighbour l-3-3-0 l-3-3-1 e) (neighbour l-3-3-1 l-3-3-2 e) (neighbour l-3-3-2 l-3-3-3 e) 51 | (neighbour l-4-0-0 l-4-0-1 e) (neighbour l-4-0-1 l-4-0-2 e) (neighbour l-4-0-2 l-4-0-3 e) 52 | (neighbour l-4-1-0 l-4-1-1 e) (neighbour l-4-1-1 l-4-1-2 e) (neighbour l-4-1-2 l-4-1-3 e) 53 | (neighbour l-4-2-0 l-4-2-1 e) (neighbour l-4-2-1 l-4-2-2 e) (neighbour l-4-2-2 l-4-2-3 e) 54 | (neighbour l-4-3-0 l-4-3-1 e) (neighbour l-4-3-1 l-4-3-2 e) (neighbour l-4-3-2 l-4-3-3 e) 55 | 56 | (neighbour l-0-0-1 l-0-0-0 w) (neighbour l-0-0-2 l-0-0-1 w) (neighbour l-0-0-3 l-0-0-2 w) 57 | (neighbour l-0-1-1 l-0-1-0 w) (neighbour l-0-1-2 l-0-1-1 w) (neighbour l-0-1-3 l-0-1-2 w) 58 | (neighbour l-0-2-1 l-0-2-0 w) (neighbour l-0-2-2 l-0-2-1 w) (neighbour l-0-2-3 l-0-2-2 w) 59 | (neighbour l-0-3-1 l-0-3-0 w) (neighbour l-0-3-2 l-0-3-1 w) (neighbour l-0-3-3 l-0-3-2 w) 60 | (neighbour l-1-0-1 l-1-0-0 w) (neighbour l-1-0-2 l-1-0-1 w) (neighbour l-1-0-3 l-1-0-2 w) 61 | (neighbour l-1-1-1 l-1-1-0 w) (neighbour l-1-1-2 l-1-1-1 w) (neighbour l-1-1-3 l-1-1-2 w) 62 | (neighbour l-1-2-1 l-1-2-0 w) (neighbour l-1-2-2 l-1-2-1 w) (neighbour l-1-2-3 l-1-2-2 w) 63 | (neighbour l-1-3-1 l-1-3-0 w) (neighbour l-1-3-2 l-1-3-1 w) (neighbour l-1-3-3 l-1-3-2 w) 64 | (neighbour l-2-0-1 l-2-0-0 w) (neighbour l-2-0-2 l-2-0-1 w) (neighbour l-2-0-3 l-2-0-2 w) 65 | (neighbour l-2-1-1 l-2-1-0 w) (neighbour l-2-1-2 l-2-1-1 w) (neighbour l-2-1-3 l-2-1-2 w) 66 | (neighbour l-2-2-1 l-2-2-0 w) (neighbour l-2-2-2 l-2-2-1 w) (neighbour l-2-2-3 l-2-2-2 w) 67 | (neighbour l-2-3-1 l-2-3-0 w) (neighbour l-2-3-2 l-2-3-1 w) (neighbour l-2-3-3 l-2-3-2 w) 68 | (neighbour l-3-0-1 l-3-0-0 w) (neighbour l-3-0-2 l-3-0-1 w) (neighbour l-3-0-3 l-3-0-2 w) 69 | (neighbour l-3-1-1 l-3-1-0 w) (neighbour l-3-1-2 l-3-1-1 w) (neighbour l-3-1-3 l-3-1-2 w) 70 | (neighbour l-3-2-1 l-3-2-0 w) (neighbour l-3-2-2 l-3-2-1 w) (neighbour l-3-2-3 l-3-2-2 w) 71 | (neighbour l-3-3-1 l-3-3-0 w) (neighbour l-3-3-2 l-3-3-1 w) (neighbour l-3-3-3 l-3-3-2 w) 72 | (neighbour l-4-0-1 l-4-0-0 w) (neighbour l-4-0-2 l-4-0-1 w) (neighbour l-4-0-3 l-4-0-2 w) 73 | (neighbour l-4-1-1 l-4-1-0 w) (neighbour l-4-1-2 l-4-1-1 w) (neighbour l-4-1-3 l-4-1-2 w) 74 | (neighbour l-4-2-1 l-4-2-0 w) (neighbour l-4-2-2 l-4-2-1 w) (neighbour l-4-2-3 l-4-2-2 w) 75 | (neighbour l-4-3-1 l-4-3-0 w) (neighbour l-4-3-2 l-4-3-1 w) (neighbour l-4-3-3 l-4-3-2 w) 76 | 77 | (neighbour l-0-0-0 l-0-1-0 n) (neighbour l-0-1-0 l-0-2-0 n) (neighbour l-0-2-0 l-0-3-0 n) 78 | (neighbour l-0-0-1 l-0-1-1 n) (neighbour l-0-1-1 l-0-2-1 n) (neighbour l-0-2-1 l-0-3-1 n) 79 | (neighbour l-0-0-2 l-0-1-2 n) (neighbour l-0-1-2 l-0-2-2 n) (neighbour l-0-2-2 l-0-3-2 n) 80 | (neighbour l-0-0-3 l-0-1-3 n) (neighbour l-0-1-3 l-0-2-3 n) (neighbour l-0-2-3 l-0-3-3 n) 81 | (neighbour l-1-0-0 l-1-1-0 n) (neighbour l-1-1-0 l-1-2-0 n) (neighbour l-1-2-0 l-1-3-0 n) 82 | (neighbour l-1-0-1 l-1-1-1 n) (neighbour l-1-1-1 l-1-2-1 n) (neighbour l-1-2-1 l-1-3-1 n) 83 | (neighbour l-1-0-2 l-1-1-2 n) (neighbour l-1-1-2 l-1-2-2 n) (neighbour l-1-2-2 l-1-3-2 n) 84 | (neighbour l-1-0-3 l-1-1-3 n) (neighbour l-1-1-3 l-1-2-3 n) (neighbour l-1-2-3 l-1-3-3 n) 85 | (neighbour l-2-0-0 l-2-1-0 n) (neighbour l-2-1-0 l-2-2-0 n) (neighbour l-2-2-0 l-2-3-0 n) 86 | (neighbour l-2-0-1 l-2-1-1 n) (neighbour l-2-1-1 l-2-2-1 n) (neighbour l-2-2-1 l-2-3-1 n) 87 | (neighbour l-2-0-2 l-2-1-2 n) (neighbour l-2-1-2 l-2-2-2 n) (neighbour l-2-2-2 l-2-3-2 n) 88 | (neighbour l-2-0-3 l-2-1-3 n) (neighbour l-2-1-3 l-2-2-3 n) (neighbour l-2-2-3 l-2-3-3 n) 89 | (neighbour l-3-0-0 l-3-1-0 n) (neighbour l-3-1-0 l-3-2-0 n) (neighbour l-3-2-0 l-3-3-0 n) 90 | (neighbour l-3-0-1 l-3-1-1 n) (neighbour l-3-1-1 l-3-2-1 n) (neighbour l-3-2-1 l-3-3-1 n) 91 | (neighbour l-3-0-2 l-3-1-2 n) (neighbour l-3-1-2 l-3-2-2 n) (neighbour l-3-2-2 l-3-3-2 n) 92 | (neighbour l-3-0-3 l-3-1-3 n) (neighbour l-3-1-3 l-3-2-3 n) (neighbour l-3-2-3 l-3-3-3 n) 93 | (neighbour l-4-0-0 l-4-1-0 n) (neighbour l-4-1-0 l-4-2-0 n) (neighbour l-4-2-0 l-4-3-0 n) 94 | (neighbour l-4-0-1 l-4-1-1 n) (neighbour l-4-1-1 l-4-2-1 n) (neighbour l-4-2-1 l-4-3-1 n) 95 | (neighbour l-4-0-2 l-4-1-2 n) (neighbour l-4-1-2 l-4-2-2 n) (neighbour l-4-2-2 l-4-3-2 n) 96 | (neighbour l-4-0-3 l-4-1-3 n) (neighbour l-4-1-3 l-4-2-3 n) (neighbour l-4-2-3 l-4-3-3 n) 97 | 98 | (neighbour l-0-1-0 l-0-0-0 s) (neighbour l-0-2-0 l-0-1-0 s) (neighbour l-0-3-0 l-0-2-0 s) 99 | (neighbour l-0-1-1 l-0-0-1 s) (neighbour l-0-2-1 l-0-1-1 s) (neighbour l-0-3-1 l-0-2-1 s) 100 | (neighbour l-0-1-2 l-0-0-2 s) (neighbour l-0-2-2 l-0-1-2 s) (neighbour l-0-3-2 l-0-2-2 s) 101 | (neighbour l-0-1-3 l-0-0-3 s) (neighbour l-0-2-3 l-0-1-3 s) (neighbour l-0-3-3 l-0-2-3 s) 102 | (neighbour l-1-1-0 l-1-0-0 s) (neighbour l-1-2-0 l-1-1-0 s) (neighbour l-1-3-0 l-1-2-0 s) 103 | (neighbour l-1-1-1 l-1-0-1 s) (neighbour l-1-2-1 l-1-1-1 s) (neighbour l-1-3-1 l-1-2-1 s) 104 | (neighbour l-1-1-2 l-1-0-2 s) (neighbour l-1-2-2 l-1-1-2 s) (neighbour l-1-3-2 l-1-2-2 s) 105 | (neighbour l-1-1-3 l-1-0-3 s) (neighbour l-1-2-3 l-1-1-3 s) (neighbour l-1-3-3 l-1-2-3 s) 106 | (neighbour l-2-1-0 l-2-0-0 s) (neighbour l-2-2-0 l-2-1-0 s) (neighbour l-2-3-0 l-2-2-0 s) 107 | (neighbour l-2-1-1 l-2-0-1 s) (neighbour l-2-2-1 l-2-1-1 s) (neighbour l-2-3-1 l-2-2-1 s) 108 | (neighbour l-2-1-2 l-2-0-2 s) (neighbour l-2-2-2 l-2-1-2 s) (neighbour l-2-3-2 l-2-2-2 s) 109 | (neighbour l-2-1-3 l-2-0-3 s) (neighbour l-2-2-3 l-2-1-3 s) (neighbour l-2-3-3 l-2-2-3 s) 110 | (neighbour l-3-1-0 l-3-0-0 s) (neighbour l-3-2-0 l-3-1-0 s) (neighbour l-3-3-0 l-3-2-0 s) 111 | (neighbour l-3-1-1 l-3-0-1 s) (neighbour l-3-2-1 l-3-1-1 s) (neighbour l-3-3-1 l-3-2-1 s) 112 | (neighbour l-3-1-2 l-3-0-2 s) (neighbour l-3-2-2 l-3-1-2 s) (neighbour l-3-3-2 l-3-2-2 s) 113 | (neighbour l-3-1-3 l-3-0-3 s) (neighbour l-3-2-3 l-3-1-3 s) (neighbour l-3-3-3 l-3-2-3 s) 114 | (neighbour l-4-1-0 l-4-0-0 s) (neighbour l-4-2-0 l-4-1-0 s) (neighbour l-4-3-0 l-4-2-0 s) 115 | (neighbour l-4-1-1 l-4-0-1 s) (neighbour l-4-2-1 l-4-1-1 s) (neighbour l-4-3-1 l-4-2-1 s) 116 | (neighbour l-4-1-2 l-4-0-2 s) (neighbour l-4-2-2 l-4-1-2 s) (neighbour l-4-3-2 l-4-2-2 s) 117 | (neighbour l-4-1-3 l-4-0-3 s) (neighbour l-4-2-3 l-4-1-3 s) (neighbour l-4-3-3 l-4-2-3 s) 118 | 119 | (on-top l-0-0-0 l-1-0-0) (on-top l-1-0-0 l-2-0-0) (on-top l-2-0-0 l-3-0-0) (on-top l-3-0-0 l-4-0-0) 120 | (on-top l-0-0-1 l-1-0-1) (on-top l-1-0-1 l-2-0-1) (on-top l-2-0-1 l-3-0-1) (on-top l-3-0-1 l-4-0-1) 121 | (on-top l-0-0-2 l-1-0-2) (on-top l-1-0-2 l-2-0-2) (on-top l-2-0-2 l-3-0-2) (on-top l-3-0-2 l-4-0-2) 122 | (on-top l-0-0-3 l-1-0-3) (on-top l-1-0-3 l-2-0-3) (on-top l-2-0-3 l-3-0-3) (on-top l-3-0-3 l-4-0-3) 123 | (on-top l-0-1-0 l-1-1-0) (on-top l-1-1-0 l-2-1-0) (on-top l-2-1-0 l-3-1-0) (on-top l-3-1-0 l-4-1-0) 124 | (on-top l-0-1-1 l-1-1-1) (on-top l-1-1-1 l-2-1-1) (on-top l-2-1-1 l-3-1-1) (on-top l-3-1-1 l-4-1-1) 125 | (on-top l-0-1-2 l-1-1-2) (on-top l-1-1-2 l-2-1-2) (on-top l-2-1-2 l-3-1-2) (on-top l-3-1-2 l-4-1-2) 126 | (on-top l-0-1-3 l-1-1-3) (on-top l-1-1-3 l-2-1-3) (on-top l-2-1-3 l-3-1-3) (on-top l-3-1-3 l-4-1-3) 127 | (on-top l-0-2-0 l-1-2-0) (on-top l-1-2-0 l-2-2-0) (on-top l-2-2-0 l-3-2-0) (on-top l-3-2-0 l-4-2-0) 128 | (on-top l-0-2-1 l-1-2-1) (on-top l-1-2-1 l-2-2-1) (on-top l-2-2-1 l-3-2-1) (on-top l-3-2-1 l-4-2-1) 129 | (on-top l-0-2-2 l-1-2-2) (on-top l-1-2-2 l-2-2-2) (on-top l-2-2-2 l-3-2-2) (on-top l-3-2-2 l-4-2-2) 130 | (on-top l-0-2-3 l-1-2-3) (on-top l-1-2-3 l-2-2-3) (on-top l-2-2-3 l-3-2-3) (on-top l-3-2-3 l-4-2-3) 131 | (on-top l-0-3-0 l-1-3-0) (on-top l-1-3-0 l-2-3-0) (on-top l-2-3-0 l-3-3-0) (on-top l-3-3-0 l-4-3-0) 132 | (on-top l-0-3-1 l-1-3-1) (on-top l-1-3-1 l-2-3-1) (on-top l-2-3-1 l-3-3-1) (on-top l-3-3-1 l-4-3-1) 133 | (on-top l-0-3-2 l-1-3-2) (on-top l-1-3-2 l-2-3-2) (on-top l-2-3-2 l-3-3-2) (on-top l-3-3-2 l-4-3-2) 134 | (on-top l-0-3-3 l-1-3-3) (on-top l-1-3-3 l-2-3-3) (on-top l-2-3-3 l-3-3-3) (on-top l-3-3-3 l-4-3-3) 135 | 136 | (blockat l-0-0-0 earth) (blockat l-0-0-1 earth) (blockat l-0-0-2 earth) (blockat l-0-0-3 earth) (blockat l-0-1-0 earth) (blockat l-0-1-1 earth) (blockat l-0-1-2 earth) (blockat l-0-1-3 earth) (blockat l-0-2-0 earth) (blockat l-0-2-1 earth) (blockat l-0-2-2 earth) (blockat l-0-2-3 earth) (blockat l-0-3-0 earth) (blockat l-0-3-1 earth) (blockat l-0-3-2 earth) (blockat l-0-3-3 earth) 137 | 138 | (empty l-1-0-0) (empty l-1-0-1) (empty l-1-0-2) (empty l-1-0-3) 139 | (empty l-1-1-0) (empty l-1-1-1) (empty l-1-1-2) (empty l-1-1-3) 140 | (empty l-1-2-0) (empty l-1-2-1) (empty l-1-2-2) (empty l-1-2-3) 141 | (empty l-1-3-0) (empty l-1-3-1) (empty l-1-3-2) (empty l-1-3-3) 142 | (empty l-2-0-0) (empty l-2-0-1) (empty l-2-0-2) (empty l-2-0-3) 143 | (empty l-2-1-0) (empty l-2-1-1) (empty l-2-1-2) (empty l-2-1-3) 144 | (empty l-2-2-0) (empty l-2-2-1) (empty l-2-2-2) (empty l-2-2-3) 145 | (empty l-2-3-0) (empty l-2-3-1) (empty l-2-3-2) (empty l-2-3-3) 146 | (empty l-3-0-0) (empty l-3-0-1) (empty l-3-0-2) (empty l-3-0-3) 147 | (empty l-3-1-0) (empty l-3-1-1) (empty l-3-1-2) (empty l-3-1-3) 148 | (empty l-3-2-0) (empty l-3-2-1) (empty l-3-2-2) (empty l-3-2-3) 149 | (empty l-3-3-0) (empty l-3-3-1) (empty l-3-3-2) (empty l-3-3-3) 150 | (empty l-4-0-0) (empty l-4-0-1) (empty l-4-0-2) (empty l-4-0-3) 151 | (empty l-4-1-0) (empty l-4-1-1) (empty l-4-1-2) (empty l-4-1-3) 152 | (empty l-4-2-0) (empty l-4-2-1) (empty l-4-2-2) (empty l-4-2-3) 153 | (empty l-4-3-0) (empty l-4-3-1) (empty l-4-3-2) (empty l-4-3-3) 154 | 155 | (= (total-cost) 0) 156 | (= (block-cost wood) 1) 157 | (= (block-cost stone) 2) 158 | (= (block-cost earth) 3) 159 | 160 | 161 | (isone n1) 162 | (prev n1 n0) (prev n2 n1) (prev n3 n2) 163 | ) 164 | 165 | (:metric minimize (total-cost)) 166 | 167 | ) 168 | -------------------------------------------------------------------------------- /tests/minecraft-costs.hddl: -------------------------------------------------------------------------------- 1 | (define (domain minecraft) 2 | (:requirements :typing) 3 | 4 | (:types 5 | location blocktype direction numbers - object 6 | 7 | ) 8 | 9 | (:predicates 10 | (empty ?location - location) 11 | (blockat ?location - location ?t - blocktype) 12 | (neighbour ?loc1 ?loc2 - location ?dir - direction) 13 | (on-top ?loc1 ?loc2 - location) 14 | (isone ?z - numbers) 15 | (prev ?z ?z2 - numbers) 16 | ) 17 | 18 | (:functions 19 | (total-cost) - number 20 | (block-cost ?b - blocktype) - number 21 | ) 22 | 23 | (:task buildhouse :parameters (?loc1 ?loc2 ?loc3 ?loc4 ?loc5 ?loc6 - location ?len ?len2 ?hgt - numbers ?t - blocktype)) 24 | (:task buildwall :parameters (?loc1 - location ?len ?hgt - numbers ?d - direction ?t - blocktype)) 25 | (:task buildroof :parameters (?loc1 - location ?len ?wdt - numbers ?d ?d2 - direction ?t - blocktype)) 26 | (:task builddoor :parameters (?loc1 - location)) 27 | (:task buildrow :parameters (?loc1 - location ?len - numbers ?d - direction ?t - blocktype)) 28 | (:task placeblockabstract :parameters (?loc1 - location ?t - blocktype)) 29 | (:task removeblockabstract :parameters (?loc1 - location)) 30 | 31 | 32 | (:method build-house-1 33 | :parameters (?loc1 ?loc2 ?loc3 ?loc4 ?loc5 ?loc6 - location ?len ?len2 ?hgt - numbers ?t - blocktype) 34 | :task (buildhouse ?loc1 ?loc2 ?loc3 ?loc4 ?loc5 ?loc6 ?len ?len2 ?hgt ?t) 35 | :precondition () 36 | :ordered-subtasks (and 37 | (buildwall ?loc1 ?len ?hgt e ?t) 38 | (buildwall ?loc2 ?len2 ?hgt n ?t) 39 | (buildwall ?loc3 ?len ?hgt w ?t) 40 | (buildwall ?loc4 ?len2 ?hgt s ?t) 41 | (builddoor ?loc5) 42 | (buildroof ?loc6 ?len ?len2 e n ?t) 43 | 44 | ) 45 | ) 46 | 47 | (:method build-wall-1 48 | :parameters (?loc1 - location ?len ?hgt - numbers ?d - direction ?t - blocktype) 49 | :task (buildwall ?loc1 ?len ?hgt ?d ?t) 50 | :precondition (and (isone ?hgt) ) 51 | :subtasks (and 52 | (buildrow ?loc1 ?len ?d ?t) 53 | ) 54 | ) 55 | 56 | (:method build-wall-2 57 | :parameters (?loc1 ?loc2 - location ?len ?hgt ?hgt2 - numbers ?d - direction ?t - blocktype) 58 | :task (buildwall ?loc1 ?len ?hgt ?d ?t) 59 | :precondition (and (not(isone ?hgt)) (prev ?hgt ?hgt2) (on-top ?loc1 ?loc2) ) 60 | :ordered-subtasks (and 61 | (buildrow ?loc1 ?len ?d ?t) 62 | (buildwall ?loc2 ?len ?hgt2 ?d ?t) 63 | ) 64 | ) 65 | 66 | (:method build-roof-1 67 | :parameters (?loc1 - location ?len ?wdt - numbers ?d ?d2 - direction ?t - blocktype) 68 | :task (buildroof ?loc1 ?len ?wdt ?d ?d2 ?t) 69 | :precondition (and (isone ?wdt) ) 70 | :subtasks (and 71 | (buildrow ?loc1 ?len ?d ?t) 72 | ) 73 | ) 74 | 75 | (:method build-roof-2 76 | :parameters (?loc1 ?loc2 - location ?len ?wdt ?wdt2 - numbers ?d ?d2 - direction ?t - blocktype) 77 | :task (buildroof ?loc1 ?len ?wdt ?d ?d2 ?t) 78 | :precondition (and (not(isone ?wdt)) (prev ?wdt ?wdt2) (neighbour ?loc1 ?loc2 ?d2) ) 79 | :ordered-subtasks (and 80 | (buildrow ?loc1 ?len ?d ?t) 81 | (buildroof ?loc2 ?len ?wdt2 ?d ?d2 ?t) 82 | ) 83 | ) 84 | 85 | (:method build-door-1 86 | :parameters (?loc1 ?loc2 - location) 87 | :task (builddoor ?loc1) 88 | :precondition (and (on-top ?loc1 ?loc2)) 89 | :ordered-subtasks (and 90 | (removeblockabstract ?loc1) 91 | (removeblockabstract ?loc2) 92 | ) 93 | ) 94 | 95 | 96 | (:method build-row-1 97 | :parameters (?loc1 - location ?len - numbers ?d - direction ?t - blocktype) 98 | :task (buildrow ?loc1 ?len ?d ?t) 99 | :precondition (and (isone ?len) ) 100 | :subtasks (and 101 | (placeblockabstract ?loc1 ?t) 102 | ) 103 | ) 104 | 105 | (:method build-row-2 106 | :parameters (?loc1 ?loc2 - location ?len ?len2 - numbers ?d - direction ?t - blocktype) 107 | :task (buildrow ?loc1 ?len ?d ?t) 108 | :precondition (and (not(isone ?len)) (prev ?len ?len2) (neighbour ?loc1 ?loc2 ?d) ) 109 | :ordered-subtasks (and 110 | (placeblockabstract ?loc1 ?t) 111 | (buildrow ?loc2 ?len2 ?d ?t) 112 | ) 113 | ) 114 | 115 | (:method build-row-3 116 | :parameters (?loc1 ?loc2 - location ?len ?len2 - numbers ?d - direction ?t - blocktype) 117 | :task (buildrow ?loc1 ?len ?d ?t) 118 | :precondition (and (not(isone ?len)) (prev ?len ?len2) (neighbour ?loc1 ?loc2 ?d) ) 119 | :ordered-subtasks (and 120 | (buildrow ?loc2 ?len2 ?d ?t) 121 | (placeblockabstract ?loc1 ?t) 122 | ) 123 | ) 124 | 125 | (:method place-block-abstract-1 126 | :parameters (?loc1 - location ?t - blocktype) 127 | :task (placeblockabstract ?loc1 ?t) 128 | :precondition (and (empty ?loc1)) 129 | :subtasks (and 130 | (placeblock ?loc1 ?t) 131 | ) 132 | ) 133 | 134 | (:method place-block-abstract-2 135 | :parameters (?loc1 - location ?t - blocktype) 136 | :task (placeblockabstract ?loc1 ?t) 137 | :precondition (and (blockat ?loc1 ?t)) 138 | :subtasks () 139 | ) 140 | 141 | (:method place-block-abstract-3 142 | :parameters (?loc1 - location ?t ?t2 - blocktype) 143 | :task (placeblockabstract ?loc1 ?t) 144 | :precondition (and (blockat ?loc1 ?t2) ) 145 | :ordered-subtasks (and 146 | (removeblock ?loc1 ?t2) 147 | (placeblock ?loc1 ?t) 148 | ) 149 | ) 150 | 151 | (:method remove-block-abstract-1 152 | :parameters (?loc1 - location) 153 | :task (removeblockabstract ?loc1) 154 | :precondition (and (empty ?loc1)) 155 | :subtasks () 156 | ) 157 | 158 | (:method remove-block-abstract-2 159 | :parameters (?loc1 - location ?t - blocktype) 160 | :task (removeblockabstract ?loc1) 161 | :precondition (and (blockat ?loc1 ?t)) 162 | :subtasks (and 163 | (removeblock ?loc1 ?t) 164 | ) 165 | ) 166 | 167 | 168 | (:action placeblock 169 | :parameters (?location - location ?t - blocktype) 170 | :precondition (and (empty ?location) ) 171 | :effect (and 172 | (increase (total-cost) (block-cost ?t)) 173 | (not (empty ?location)) (blockat ?location ?t)) ) 174 | 175 | (:action removeblock 176 | :parameters (?location - location ?t - blocktype) 177 | :precondition (and (not(empty ?location)) ) 178 | :effect (and 179 | (increase (total-cost) 1) 180 | (empty ?location) (not(blockat ?location ?t))) ) 181 | 182 | ) 183 | -------------------------------------------------------------------------------- /tests/plan-for-transport-pfile01-non-existing-method.txt: -------------------------------------------------------------------------------- 1 | ==> 2 | 0 drive truck-0 city-loc-2 city-loc-1 3 | 1 pick-up truck-0 city-loc-1 package-1 capacity-0 capacity-1 4 | 2 drive truck-0 city-loc-1 city-loc-2 5 | 3 drop truck-0 city-loc-2 package-1 capacity-0 capacity-1 6 | 4 drive truck-0 city-loc-2 city-loc-1 7 | 5 pick-up truck-0 city-loc-1 package-0 capacity-0 capacity-1 8 | 6 drive truck-0 city-loc-1 city-loc-0 9 | 7 drop truck-0 city-loc-0 package-0 capacity-0 capacity-1 10 | root 8 11 | 8 __top -> __top_method 13 16 12 | 9 get-to truck-0 city-loc-1 -> m-drive 0 13 | 10 load truck-0 city-loc-1 package-0 -> m-load 5 14 | 11 unload truck-0 city-loc-0 package-0 -> m-unload 7 15 | 12 load truck-0 city-loc-1 package-1 -> m-load 1 16 | 13 deliver package-0 city-loc-0 -> m-deliver 15 10 17 11 17 | 14 get-to truck-0 city-loc-2 -> m-drive-to 2 18 | 15 get-to truck-0 city-loc-1 -> m-drive-to 4 19 | 16 deliver package-1 city-loc-2 -> m-deliver 9 12 14 18 20 | 17 get-to truck-0 city-loc-0 -> m-drive-to 6 21 | 18 unload truck-0 city-loc-2 package-1 -> m-unload 3 22 | -------------------------------------------------------------------------------- /tests/plan-for-transport-pfile01-notop.txt: -------------------------------------------------------------------------------- 1 | ==> 2 | 0 drive truck-0 city-loc-2 city-loc-1 3 | 1 pick-up truck-0 city-loc-1 package-1 capacity-0 capacity-1 4 | 2 drive truck-0 city-loc-1 city-loc-2 5 | 3 drop truck-0 city-loc-2 package-1 capacity-0 capacity-1 6 | 4 drive truck-0 city-loc-2 city-loc-1 7 | 5 pick-up truck-0 city-loc-1 package-0 capacity-0 capacity-1 8 | 6 drive truck-0 city-loc-1 city-loc-0 9 | 7 drop truck-0 city-loc-0 package-0 capacity-0 capacity-1 10 | root 13 16 11 | 9 get-to truck-0 city-loc-1 -> m-drive-to 0 12 | 10 load truck-0 city-loc-1 package-0 -> m-load 5 13 | 11 unload truck-0 city-loc-0 package-0 -> m-unload 7 14 | 12 load truck-0 city-loc-1 package-1 -> m-load 1 15 | 13 deliver package-0 city-loc-0 -> m-deliver 15 10 17 11 16 | 14 get-to truck-0 city-loc-2 -> m-drive-to 2 17 | 15 get-to truck-0 city-loc-1 -> m-drive-to 4 18 | 16 deliver package-1 city-loc-2 -> m-deliver 9 12 14 18 19 | 17 get-to truck-0 city-loc-0 -> m-drive-to 6 20 | 18 unload truck-0 city-loc-2 package-1 -> m-unload 3 21 | -------------------------------------------------------------------------------- /tests/plan-for-transport-pfile01-total-order.txt: -------------------------------------------------------------------------------- 1 | ==> 2 | 0 drive truck_0 city_loc_2 city_loc_1 3 | 1 pick_up truck_0 city_loc_1 package_0 capacity_0 capacity_1 4 | 2 drive truck_0 city_loc_1 city_loc_0 5 | 3 drop truck_0 city_loc_0 package_0 capacity_0 capacity_1 6 | 4 drive truck_0 city_loc_0 city_loc_1 7 | 5 pick_up truck_0 city_loc_1 package_1 capacity_0 capacity_1 8 | 7 drop truck_0 city_loc_2 package_1 capacity_0 capacity_1 9 | 6 drive truck_0 city_loc_1 city_loc_2 10 | root 16 11 | 8 unload truck_0 city_loc_0 package_0 -> m_unload_ordering_0 3 12 | 9 load truck_0 city_loc_1 package_1 -> m_load_ordering_0 5 13 | 10 get_to truck_0 city_loc_0 -> m_drive_to_ordering_0 2 14 | 11 unload truck_0 city_loc_2 package_1 -> m_unload_ordering_0 7 15 | 12 load truck_0 city_loc_1 package_0 -> m_load_ordering_0 1 16 | 13 get_to truck_0 city_loc_1 -> m_drive_to_ordering_0 0 17 | 14 deliver package_0 city_loc_0 -> m_deliver_ordering_0 13 12 10 8 18 | 15 get_to truck_0 city_loc_1 -> m_drive_to_ordering_0 4 19 | 16 __top -> __top_method 14 18 20 | 17 get_to truck_0 city_loc_2 -> m_drive_to_ordering_0 6 21 | 18 deliver package_1 city_loc_2 -> m_deliver_ordering_0 15 9 17 11 22 | -------------------------------------------------------------------------------- /tests/plan-for-transport-pfile01-wrong.txt: -------------------------------------------------------------------------------- 1 | ==> 2 | 0 drive truck-0 city-loc-2 city-loc-1 3 | 1 pick-up truck-0 city-loc-1 package-1 capacity-0 capacity-1 4 | 2 drive truck-0 city-loc-1 city-loc-2 5 | 3 drive truck-0 city-loc-2 city-loc-1 6 | 4 drive truck-0 city-loc-1 city-loc-2 7 | 5 drop truck-0 city-loc-2 package-1 capacity-0 capacity-1 8 | 6 drive truck-0 city-loc-2 city-loc-1 9 | 7 pick-up truck-0 city-loc-1 package-0 capacity-0 capacity-1 10 | 8 drive truck-0 city-loc-1 city-loc-0 11 | 9 drop truck-0 city-loc-0 package-0 capacity-0 capacity-1 12 | root 13 13 | 10 deliver package-1 city-loc-2 -> m-deliver 11 15 17 19 14 | 11 unload truck-0 city-loc-2 package-1 -> m-unload 5 15 | 12 get-to truck-0 city-loc-0 -> m-drive-to 8 16 | 13 __top -> __top_method 10 20 17 | 14 get-to truck-0 city-loc-1 -> m-drive-to 3 18 | 15 get-to truck-0 city-loc-2 -> m-drive-to-via 14 4 19 | 16 load truck-0 city-loc-1 package-0 -> m-load 7 20 | 17 get-to truck-0 city-loc-1 -> m-drive-to 0 21 | 18 get-to truck-0 city-loc-1 -> m-drive-to-via 6 22 22 | 19 load truck-0 city-loc-1 package-1 -> m-load 1 23 | 20 deliver package-0 city-loc-0 -> m-deliver 12 16 18 21 24 | 21 unload truck-0 city-loc-0 package-0 -> m-unload 9 25 | 22 get-to truck-0 city-loc-2 -> m-drive-to 2 26 | -------------------------------------------------------------------------------- /tests/plan-for-transport-pfile01.txt: -------------------------------------------------------------------------------- 1 | ==> 2 | 0 drive truck-0 city-loc-2 city-loc-1 3 | 1 pick-up truck-0 city-loc-1 package-1 capacity-0 capacity-1 4 | 2 drive truck-0 city-loc-1 city-loc-2 5 | 3 drop truck-0 city-loc-2 package-1 capacity-0 capacity-1 6 | 4 drive truck-0 city-loc-2 city-loc-1 7 | 5 pick-up truck-0 city-loc-1 package-0 capacity-0 capacity-1 8 | 6 drive truck-0 city-loc-1 city-loc-0 9 | 7 drop truck-0 city-loc-0 package-0 capacity-0 capacity-1 10 | root 8 11 | 8 __top -> __top_method 13 16 12 | 9 get-to truck-0 city-loc-1 -> m-drive-to 0 13 | 10 load truck-0 city-loc-1 package-0 -> m-load 5 14 | 11 unload truck-0 city-loc-0 package-0 -> m-unload 7 15 | 12 load truck-0 city-loc-1 package-1 -> m-load 1 16 | 13 deliver package-0 city-loc-0 -> m-deliver 15 10 17 11 17 | 14 get-to truck-0 city-loc-2 -> m-drive-to 2 18 | 15 get-to truck-0 city-loc-1 -> m-drive-to 4 19 | 16 deliver package-1 city-loc-2 -> m-deliver 9 12 14 18 20 | 17 get-to truck-0 city-loc-0 -> m-drive-to 6 21 | 18 unload truck-0 city-loc-2 package-1 -> m-unload 3 22 | -------------------------------------------------------------------------------- /tests/um-translog-01.plan: -------------------------------------------------------------------------------- 1 | 2 | #1 "40 sat:90:solved"="true";"30 problem:05:number of primitive actions"="22";"30 problem:01:number of constants"="0";"30 problem:04:number of abstract actions"="9";"02 properties:04:tail recursive"="true";"00 global:80:peak memory"="158099552";"40 sat:20:state formula"="13455";"40 sat:01:number of variables"="6397";"40 sat:14:K offset"="0";"40 sat:30:number of paths"="26";"40 sat:00:plan length"="-1";"40 sat:50:number of ordering clauses"="8476";"02 properties:02:mostly acyclic"="true";"30 problem:06:number of methods"="9";"30 problem:07:number of primitive shop actions"="0";"02 properties:05:totally ordered"="true";"02 properties:06:last task in all methods"="true";"30 problem:03:number of actions"="31";"30 problem:08:number of primitive non-shop actions"="22";"30 problem:02:number of predicates"="23";"40 sat:03:number of horn"="11697";"40 sat:15:K chosen value"="2";"30 problem:10:average method size"="3";"02 properties:03:regular"="true";"30 problem:09:size of largest method"="26";"40 sat:03:average size of clauses"="3.2286301269352116";"40 sat:02:number of clauses"="13629";"40 sat:50:number of state clauses"="4979";"40 sat:03:number of assert"="11";"40 sat:22:method children clauses"="0";"00 global:90:planner result"="SOLUTION";"02 properties:01:acyclic"="true";"40 sat:50:number of decomposition clauses"="174";"00 global:02:randomseed"="42";"40 sat:91:timeout"="false";"01 parsing:01:file parser"="555";"01 parsing:08:flatten formula"="173";"40 sat:00:total"="594";"40 sat:16:generate state formula"="474";"40 sat:20:transform to DIMACS"="43";"40 sat:11:generate path decomposition tree"="85";"02 preprocessing:07:compile methods with identical tasks"="73";"01 parsing:07:strip domain of hybridity"="2";"02 preprocessing:08:removing unnecessary predicates"="37";"01 parsing:03:closed world assumption"="66";"02 preprocessing:11:lifted reachabiltiy analysis"="297";"01 parsing:02:sort expansion"="528";"40 sat:12:normalise path decomposition tree"="17";"40 sat:40:SAT solver"="10";"01 parsing:00:total"="1460";"40 sat:10:generate formula"="479";"01 parsing:04:inherit preconditions"="0";"40 sat:41:SAT solver for K=0002"="10";"02 preprocessing:01:compile negative preconditions"="148";"00 total:00:total"="4520";"40 sat:13:sog optimisation"="34";"02 preprocessing:12:grounded planning graph analysis"="445";"02 preprocessing:02:compile unit methods"="0";"02 preprocessing:23:grounded task decomposition graph analysis"="221";"02 preprocessing:04:split parameter"="42";"01 parsing:05:shop methods"="3";"01 parsing:06:eliminate identical variables"="133";"40 sat:15:translate path decomposition tree to clauses"="111";"02 preprocessing:05:expand choiceless abstract tasks"="189";"02 preprocessing:00:total"="1582";"02 preprocessing:99:create artificial top task"="1";"02 preprocessing:84:grounding"="95" 3 | ==> 4 | 0 collect_fees Drucker 5 | 1 attach_conveyor_ramp FlugzeugLufthansa Plane_RampStuttgart FlughafenStuttgart 6 | 2 open_door FlugzeugLufthansa 7 | 3 load_package Drucker FlugzeugLufthansa FlughafenStuttgart 8 | 4 close_door FlugzeugLufthansa 9 | 5 detach_conveyor_ramp FlugzeugLufthansa Plane_RampStuttgart FlughafenStuttgart 10 | 6 move_vehicle_no_traincar FlugzeugLufthansa FlughafenStuttgart Stuttgart_Paris_Air_Route FlughafenParis 11 | 7 attach_conveyor_ramp FlugzeugLufthansa Plane_RampParis FlughafenParis 12 | 8 open_door FlugzeugLufthansa 13 | 9 unload_package Drucker FlugzeugLufthansa FlughafenParis 14 | 10 close_door FlugzeugLufthansa 15 | 11 detach_conveyor_ramp FlugzeugLufthansa Plane_RampParis FlughafenParis 16 | 12 go_through_two_tcenters_via_hub_not_hazardous FlughafenStuttgart HeathrowAirport Stuttgart London BadenWuerttemberg LondonRegion FlughafenParis 17 | 13 attach_conveyor_ramp FlugzeugAirFrance Plane_RampParis FlughafenParis 18 | 14 open_door FlugzeugAirFrance 19 | 15 load_package Drucker FlugzeugAirFrance FlughafenParis 20 | 16 close_door FlugzeugAirFrance 21 | 17 detach_conveyor_ramp FlugzeugAirFrance Plane_RampParis FlughafenParis 22 | 18 move_vehicle_no_traincar FlugzeugAirFrance FlughafenParis Paris_London_Air_Route HeathrowAirport 23 | 19 attach_conveyor_ramp FlugzeugAirFrance Plane_RampHeathrow HeathrowAirport 24 | 20 open_door FlugzeugAirFrance 25 | 21 unload_package Drucker FlugzeugAirFrance HeathrowAirport 26 | 22 close_door FlugzeugAirFrance 27 | 23 detach_conveyor_ramp FlugzeugAirFrance Plane_RampHeathrow HeathrowAirport 28 | 24 go_through_two_tcenters_tt FlughafenStuttgart HeathrowAirport Stuttgart London 29 | 25 deliver_p Drucker 30 | root 30 31 | 26 close_door FlugzeugLufthansa -> __UNIQUE-replacement_6 4 32 | 27 open_door FlugzeugAirFrance -> __UNIQUE-replacement_3 20 33 | 28 close_door FlugzeugLufthansa -> __UNIQUE-replacement_7 10 34 | 29 close_door FlugzeugAirFrance -> __UNIQUE-replacement_0 16 35 | 30 transport Drucker FlughafenStuttgart HeathrowAirport -> <<<<<<<<<<<<<<<<<<<;pickup[Drucker];method_pickup_normal;0;-1,1,2>;deliver[Drucker];method_deliver_dp;2;0,1,-1>;helper_carry_tt[Drucker,FlughafenStuttgart,Stuttgart,HeathrowAirport,London];method_helper_carry_cvh;1;0,-1,-2,2>;carry_via_hub[Drucker,FlughafenStuttgart,HeathrowAirport];method_carry_via_hub_not_hazardous;1;0,-1,2,3>;helper_carry_via_hub_not_hazardous[Drucker,FlughafenStuttgart,Stuttgart,BadenWuerttemberg,FlughafenParis,HeathrowAirport,London,LondonRegion];method_helper_carry_via_hub_not_hazardous;1;0,-1,-2,-3,2,3>;carry_direct[Drucker,FlughafenParis,HeathrowAirport];method_carry_direct;3;0,1,2,-1,4,5>;carry_direct[Drucker,FlughafenStuttgart,FlughafenParis];method_carry_direct;1;0,-1,2,3,4,5>;helper_carry_direct[FlugzeugAirFrance,Drucker,FlughafenParis,HeathrowAirport];method_helper_carry_direct_noMoveFirst;3;0,1,2,-1,-2,-3,4,5>;helper_carry_direct[FlugzeugLufthansa,Drucker,FlughafenStuttgart,FlughafenParis];method_helper_carry_direct_noMoveFirst;1;0,-1,-2,-3,2,3,4,5,6,7>;load_top[Drucker,FlugzeugAirFrance,FlughafenParis];method_load_top_normal;5;0,1,2,3,4,-1,6,7,8,9>;unload_top[Drucker,FlugzeugAirFrance,HeathrowAirport];method_unload_top_normal;7;0,1,2,3,4,5,6,-1,8,9>;move[FlugzeugAirFrance,FlughafenParis,HeathrowAirport];method_move_no_traincar;6;0,1,2,3,4,5,-1,7,8,9>;load_top[Drucker,FlugzeugLufthansa,FlughafenStuttgart];method_load_top_normal;1;0,-1,2,3,4,5,6,7,8,9>;unload_top[Drucker,FlugzeugLufthansa,FlughafenParis];method_unload_top_normal;3;0,1,2,-1,4,5,6,7,8,9>;move[FlugzeugLufthansa,FlughafenStuttgart,FlughafenParis];method_move_no_traincar;2;0,1,-1,3,4,5,6,7,8,9>;load[Drucker,FlugzeugAirFrance,FlughafenParis];method_load_airplane;5;0,1,2,3,4,-1,-2,-3,-4,-5,6,7,8,9>;unload[Drucker,FlugzeugAirFrance,HeathrowAirport];method_unload_airplane;11;0,1,2,3,4,5,6,7,8,9,10,-1,-2,-3,-4,-5,12,13>;load[Drucker,FlugzeugLufthansa,FlughafenStuttgart];method_load_airplane;1;0,-1,-2,-3,-4,-5,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17>;unload[Drucker,FlugzeugLufthansa,FlughafenParis];method_unload_airplane;7;0,1,2,3,4,5,6,-1,-2,-3,-4,-5,8,9,10,11,12,13,14,15,16,17,18,19,20,21> 0 1 34 3 26 5 6 7 32 9 28 11 12 13 33 15 29 17 18 19 27 21 31 23 24 25 36 | 31 close_door FlugzeugAirFrance -> __UNIQUE-replacement_1 22 37 | 32 open_door FlugzeugLufthansa -> __UNIQUE-replacement_5 8 38 | 33 open_door FlugzeugAirFrance -> __UNIQUE-replacement_2 14 39 | 34 open_door FlugzeugLufthansa -> __UNIQUE-replacement_4 2 40 | -------------------------------------------------------------------------------- /tests/woodworking-00.plan: -------------------------------------------------------------------------------- 1 | #1 "40 sat:90:solved"="true";"30 problem:05:number of primitive actions"="89";"30 problem:01:number of constants"="0";"30 problem:04:number of abstract actions"="54";"02 properties:04:tail recursive"="true";"00 global:80:peak memory"="112142104";"40 sat:20:state formula"="21766";"40 sat:01:number of variables"="8765";"40 sat:14:K offset"="0";"40 sat:30:number of paths"="12";"40 sat:00:plan length"="-1";"40 sat:50:number of ordering clauses"="7857";"02 properties:02:mostly acyclic"="true";"30 problem:06:number of methods"="199";"30 problem:07:number of primitive shop actions"="0";"02 properties:05:totally ordered"="false";"02 properties:06:last task in all methods"="false";"30 problem:03:number of actions"="143";"30 problem:08:number of primitive non-shop actions"="89";"30 problem:02:number of predicates"="25";"40 sat:03:number of horn"="22050";"40 sat:15:K chosen value"="6";"30 problem:10:average method size"="1";"02 properties:03:regular"="false";"30 problem:09:size of largest method"="3";"40 sat:03:average size of clauses"="3.0031768012055555";"40 sat:02:number of clauses"="24553";"40 sat:50:number of state clauses"="13909";"40 sat:03:number of assert"="12";"40 sat:22:method children clauses"="0";"00 global:90:planner result"="SOLUTION";"02 properties:01:acyclic"="true";"40 sat:50:number of decomposition clauses"="2787";"00 global:02:randomseed"="42";"40 sat:91:timeout"="false";"01 parsing:01:file parser"="373";"01 parsing:08:flatten formula"="47";"40 sat:41:SAT solver for K=0004"="0";"40 sat:00:total"="726";"40 sat:16:generate state formula"="523";"40 sat:20:transform to DIMACS"="70";"40 sat:11:generate path decomposition tree"="169";"02 preprocessing:07:compile methods with identical tasks"="5";"01 parsing:07:strip domain of hybridity"="120";"02 preprocessing:08:removing unnecessary predicates"="114";"01 parsing:03:closed world assumption"="71";"02 preprocessing:11:lifted reachabiltiy analysis"="96";"01 parsing:02:sort expansion"="215";"40 sat:12:normalise path decomposition tree"="36";"40 sat:40:SAT solver"="20";"01 parsing:00:total"="905";"40 sat:10:generate formula"="531";"40 sat:41:SAT solver for K=0005"="10";"01 parsing:04:inherit preconditions"="0";"02 preprocessing:01:compile negative preconditions"="42";"00 total:00:total"="4519";"40 sat:13:sog optimisation"="63";"02 preprocessing:12:grounded planning graph analysis"="558";"02 preprocessing:02:compile unit methods"="0";"02 preprocessing:23:grounded task decomposition graph analysis"="448";"40 sat:41:SAT solver for K=0006"="10";"02 preprocessing:04:split parameter"="75";"01 parsing:05:shop methods"="3";"01 parsing:06:eliminate identical variables"="72";"40 sat:15:translate path decomposition tree to clauses"="150";"02 preprocessing:05:expand choiceless abstract tasks"="258";"02 preprocessing:00:total"="1767";"02 preprocessing:99:create artificial top task"="6";"02 preprocessing:84:grounding"="147" 2 | ==> 3 | 0 do_plane p2 verysmooth natural varnished 4 | 1 do_grind_untreated p2 grinder0 smooth natural 5 | 2 do_saw_medium b0 p1 pine rough s3 s2 s1 6 | 3 do_plane p0 smooth red varnished 7 | 4 do_plane p1 rough natural untreated 8 | 5 do_spray_varnish p2 spray_varnisher0 red verysmooth 9 | 6 do_glaze p0 glazer0 red 10 | 7 do_spray_varnish p1 spray_varnisher0 red smooth 11 | root 15 12 | 8 process___top_0_sip_3 p2 red -> ___top_0_3 13 13 | 9 do_colour p2 red spray_varnisher0 -> method1 5 14 | 10 grindNplane_method16_sip_4 p2 verysmooth untreated -> <_method16_4;grindNplane[p2,verysmooth,natural,varnished,smooth,natural,untreated];method7;0;-1> 0 15 | 11 do_grind_untreated_method16_sip_2 p2 grinder0 -> _method16_2 1 16 | 12 process___top_0_sip_2 p1 red smooth -> ___top_0_2 14 17 | 13 process p2 red verysmooth verysmooth -> method16 10 11 16 18 | 14 process p1 red rough smooth -> <<;cut_and_saw[b0,p1,pine,rough];method10;0;-1,1,2>;do_saw[b0,p1,pine,rough];method8;0;-1,1,2> 2 21 18 19 | 15 __MakeMethodSubTasksUniqueCompilation__top_4 -> __top_4 19 20 | 16 do_colour_method16_sip_3 red -> _method16_3 9 21 | 17 grindNplane p1 rough natural untreated smooth natural untreated -> method7 4 22 | 18 do_colour_method14_sip_4 p1 red -> <_method14_4;do_colour[p1,red,spray_varnisher0];method1;0;-1> 7 23 | 19 __choicelessATCompilation__top_1 -> __top_1 8 12 23 24 | 20 do_colour_method12_sip_3 p0 red -> <_method12_3;do_colour[p0,red,glazer0];method2;0;-1> 6 25 | 21 grindNplane_method14_sip_3 p1 rough smooth untreated -> _method14_3 17 26 | 22 grindNplane_method12_sip_2 p0 smooth smooth untreated -> <_method12_2;grindNplane[p0,smooth,red,varnished,smooth,natural,untreated];method7;0;-1> 3 27 | 23 process___top_0_sip_4 p0 red -> <___top_0_4;process[p0,red,smooth,smooth];method12;0;-1,-2> 22 20 28 | -------------------------------------------------------------------------------- /tests/zenotravel-01.plan: -------------------------------------------------------------------------------- 1 | #1 "40 sat:90:solved"="true";"30 problem:05:number of primitive actions"="107";"30 problem:01:number of constants"="0";"30 problem:04:number of abstract actions"="21";"02 properties:04:tail recursive"="true";"00 global:80:peak memory"="43094240";"40 sat:20:state formula"="6260";"40 sat:01:number of variables"="2049";"40 sat:14:K offset"="0";"40 sat:30:number of paths"="8";"40 sat:00:plan length"="-1";"40 sat:50:number of ordering clauses"="2515";"02 properties:02:mostly acyclic"="true";"30 problem:06:number of methods"="106";"30 problem:07:number of primitive shop actions"="24";"02 properties:05:totally ordered"="false";"02 properties:06:last task in all methods"="false";"30 problem:03:number of actions"="128";"30 problem:08:number of primitive non-shop actions"="83";"30 problem:02:number of predicates"="19";"40 sat:03:number of horn"="6110";"40 sat:15:K chosen value"="4";"30 problem:10:average method size"="2";"02 properties:03:regular"="false";"30 problem:09:size of largest method"="5";"40 sat:03:average size of clauses"="2.653784918222608";"40 sat:02:number of clauses"="6909";"40 sat:50:number of state clauses"="3745";"40 sat:03:number of assert"="10";"40 sat:22:method children clauses"="0";"00 global:90:planner result"="SOLUTION";"02 properties:01:acyclic"="true";"40 sat:50:number of decomposition clauses"="649";"00 global:02:randomseed"="42";"40 sat:91:timeout"="false";"01 parsing:01:file parser"="311";"01 parsing:08:flatten formula"="78";"40 sat:41:SAT solver for K=0004"="0";"40 sat:00:total"="432";"40 sat:16:generate state formula"="324";"40 sat:20:transform to DIMACS"="24";"40 sat:11:generate path decomposition tree"="98";"02 preprocessing:07:compile methods with identical tasks"="15";"01 parsing:07:strip domain of hybridity"="3";"02 preprocessing:08:removing unnecessary predicates"="106";"01 parsing:03:closed world assumption"="70";"02 preprocessing:11:lifted reachabiltiy analysis"="72";"01 parsing:02:sort expansion"="115";"40 sat:12:normalise path decomposition tree"="16";"40 sat:40:SAT solver"="0";"01 parsing:00:total"="649";"40 sat:10:generate formula"="328";"01 parsing:04:inherit preconditions"="0";"02 preprocessing:01:compile negative preconditions"="35";"00 total:00:total"="2993";"40 sat:13:sog optimisation"="29";"02 preprocessing:12:grounded planning graph analysis"="405";"02 preprocessing:02:compile unit methods"="0";"02 preprocessing:23:grounded task decomposition graph analysis"="320";"02 preprocessing:04:split parameter"="35";"01 parsing:05:shop methods"="21";"01 parsing:06:eliminate identical variables"="49";"40 sat:15:translate path decomposition tree to clauses"="91";"02 preprocessing:05:expand choiceless abstract tasks"="46";"40 sat:41:SAT solver for K=0003"="0";"02 preprocessing:00:total"="1225";"02 preprocessing:99:create artificial top task"="2";"02 preprocessing:84:grounding"="163" 2 | ==> 3 | 0 board p1 a1 c1 4 | 1 fly a1 c1 c2 f1 f0 5 | 2 debark p1 a1 c1 6 | root 7 7 | 3 upper-move-aircraft a1 c2 -> m4-do 6 8 | 4 transport-person p1 c1 -> m2 0 9 2 9 | 5 transport-person p2 c3 -> m1 10 | 6 move-aircraft a1 c1 c2 -> m5-case1 1 11 | 7 __MakeMethodSubTasksUniqueCompilation__top_2 -> __top_2 8 12 | 8 __choicelessATCompilation__top_1 -> <__top_1;transport-aircraft[a1,c2];m6;2;-1,0,1> 3 5 4 13 | 9 upper-move-aircraft a1 c1 -> m4-abort 14 | --------------------------------------------------------------------------------