├── tests ├── __init__.py ├── test_planning_graph_planner.py ├── test_pddl_adapter.py └── test_planning_graph.py ├── planning_graph ├── __init__.py ├── pddl_adapter.py ├── planning_graph_planner.py └── planning_graph.py ├── domain ├── planning_graph.png ├── dock-worker-robot-problem.pddl └── dock-worker-robot-domain.pddl ├── requirements.txt ├── pddlpy ├── __init__.py ├── LICENSE.txt ├── pddl.py ├── pddlListener.py └── pddlLexer.py ├── .circleci └── config.yml ├── setup.py ├── .gitignore ├── README.md └── LICENSE /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /planning_graph/__init__.py: -------------------------------------------------------------------------------- 1 | from planning_graph import * # noqa -------------------------------------------------------------------------------- /domain/planning_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debbynirwan/planning_graph/HEAD/domain/planning_graph.png -------------------------------------------------------------------------------- /domain/dock-worker-robot-problem.pddl: -------------------------------------------------------------------------------- 1 | ;; a simple DWR problem with 2 robots and 2 locations 2 | (define (problem dwrpb1) 3 | (:domain dock-worker-robot-simple) 4 | 5 | (:objects 6 | robr robq - robot 7 | loc1 loc2 - location 8 | conta contb - container) 9 | 10 | (:init 11 | (adjacent loc1 loc2) 12 | (adjacent loc2 loc1) 13 | 14 | (in conta loc1) 15 | (in contb loc2) 16 | 17 | (atl robr loc1) 18 | (atl robq loc2) 19 | 20 | (unloaded robr) 21 | (unloaded robq) 22 | ) 23 | 24 | ;; a2, b1 25 | (:goal 26 | (and 27 | (in contb loc1) 28 | (in conta loc2) 29 | )) ) 30 | -------------------------------------------------------------------------------- /tests/test_planning_graph_planner.py: -------------------------------------------------------------------------------- 1 | from planning_graph.planning_graph_planner import GraphPlanner 2 | from planning_graph.planning_graph import PlanningGraph 3 | 4 | 5 | class TestGraphPlanner: 6 | 7 | def test_plan(self): 8 | planning_graph = PlanningGraph( 9 | 'domain/dock-worker-robot-domain.pddl', 10 | 'domain/dock-worker-robot-problem.pddl') 11 | graph = planning_graph.create(max_num_of_levels=100) 12 | assert graph.fixed_point is False 13 | 14 | goal = planning_graph.goal 15 | graph_planner = GraphPlanner() 16 | layered_plan = graph_planner.plan(graph, goal) 17 | assert len(layered_plan.data) == 4 18 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | antlr4-python3-runtime==4.7 2 | attrs==20.3.0 3 | bleach==3.3.0 4 | certifi==2020.12.5 5 | chardet==4.0.0 6 | colorama==0.4.4 7 | coverage==5.4 8 | docutils==0.16 9 | flake8==3.8.4 10 | idna==2.10 11 | iniconfig==1.1.1 12 | keyring==22.0.1 13 | mccabe==0.6.1 14 | packaging==20.9 15 | pkginfo==1.7.0 16 | pluggy==0.13.1 17 | py==1.10.0 18 | pycodestyle==2.6.0 19 | pydot==1.4.1 20 | pyflakes==2.2.0 21 | Pygments==2.7.4 22 | pyparsing==2.4.7 23 | pytest==6.2.2 24 | pytest-cov==2.11.1 25 | readme-renderer==28.0 26 | requests==2.25.1 27 | requests-toolbelt==0.9.1 28 | rfc3986==1.4.0 29 | six==1.15.0 30 | toml==0.10.2 31 | tqdm==4.56.1 32 | twine==3.3.0 33 | urllib3==1.26.3 34 | webencodings==0.5.1 35 | -------------------------------------------------------------------------------- /pddlpy/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # 5 | # Copyright 2015 Hernán M. Foffani 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | # 20 | 21 | from .pddl import * # noqa 22 | 23 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Python CircleCI 2.0 configuration file 2 | version: 2 3 | jobs: 4 | build: 5 | docker: 6 | - image: circleci/python:3.8 7 | 8 | working_directory: ~/repo 9 | 10 | steps: 11 | # Step 1: obtain repo from GitHub 12 | - checkout 13 | # Step 2: create virtual env and install dependencies 14 | - run: 15 | name: install dependencies 16 | command: | 17 | python3 -m venv venv 18 | . venv/bin/activate 19 | pip install -r requirements.txt 20 | # Step 3: run linter and tests 21 | - run: 22 | name: run tests 23 | command: | 24 | . venv/bin/activate 25 | flake8 --exclude=venv*,pddlpy --statistics 26 | pytest -v --cov=planning_graph 27 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open("README.md", "r", encoding="utf-8") as fh: 4 | long_description = fh.read() 5 | 6 | setuptools.setup( 7 | name="planning-graph", 8 | version="0.0.1", 9 | author="Debby Nirwan", 10 | author_email="debby_nirwan@yahoo.com", 11 | description="Planning Graph for AI Planning", 12 | long_description=long_description, 13 | long_description_content_type="text/markdown", 14 | url="https://github.com/debbynirwan/planning_graph", 15 | packages=setuptools.find_packages(), 16 | classifiers=[ 17 | "Programming Language :: Python :: 3", 18 | "License :: OSI Approved :: Apache Software License", 19 | "Operating System :: OS Independent", 20 | ], 21 | python_requires='>=3.6', 22 | license="Apache License, Version 2.0", 23 | platforms="Python 3", 24 | ) 25 | -------------------------------------------------------------------------------- /tests/test_pddl_adapter.py: -------------------------------------------------------------------------------- 1 | from planning_graph.pddl_adapter import PlanningProblem 2 | 3 | 4 | initial_state = [("adjacent", "loc1", "loc2"), 5 | ("adjacent", "loc2", "loc1"), 6 | ("in", "conta", "loc1"), 7 | ("in", "contb", "loc2"), 8 | ("atl", "robr", "loc1"), 9 | ("atl", "robq", "loc2"), 10 | ("unloaded", "robr"), 11 | ("unloaded", "robq")] 12 | 13 | goal_state = [("in", "contb", "loc1"), 14 | ("in", "conta", "loc2")] 15 | 16 | 17 | class TestPlanningProblem: 18 | 19 | def test_constructor(self): 20 | pp = PlanningProblem("domain/dock-worker-robot-domain.pddl", 21 | "domain/dock-worker-robot-problem.pddl") 22 | 23 | assert type(pp.initial_state) is set 24 | assert type(pp.goal_state) is set 25 | assert type(pp.actions) is list 26 | 27 | def test_initial_state(self): 28 | pp = PlanningProblem("domain/dock-worker-robot-domain.pddl", 29 | "domain/dock-worker-robot-problem.pddl") 30 | assert pp.initial_state == set(initial_state) 31 | 32 | def test_goal_state(self): 33 | pp = PlanningProblem("domain/dock-worker-robot-domain.pddl", 34 | "domain/dock-worker-robot-problem.pddl") 35 | print(f"{pp.actions}") 36 | assert pp.goal_state == set(goal_state) 37 | -------------------------------------------------------------------------------- /domain/dock-worker-robot-domain.pddl: -------------------------------------------------------------------------------- 1 | ;; Specification in PDDL1 of the DWR domain 2 | 3 | (define (domain dock-worker-robot-simple) 4 | (:requirements :strips :typing ) 5 | (:types 6 | location ; there are several connected locations in the harbor 7 | robot ; holds at most 1 container, only 1 robot per location 8 | container) 9 | 10 | (:predicates 11 | (adjacent ?l1 ?l2 - location) ; location ?l1 is adjacent ot ?l2 12 | (atl ?r - robot ?l - location) ; robot ?r is at location ?l 13 | (loaded ?r - robot ?c - container ) ; robot ?r is loaded with container ?c 14 | (unloaded ?r - robot) ; robot ?r is empty 15 | (in ?c - container ?l - location) ; container ?c is within location ?l 16 | ) 17 | 18 | ;; there are 3 operators in this domain: 19 | 20 | ;; moves a robot between two adjacent locations 21 | (:action move 22 | :parameters (?r - robot ?from ?to - location) 23 | :precondition (and (adjacent ?from ?to) (atl ?r ?from) ) 24 | :effect (and (atl ?r ?to) 25 | (not (atl ?r ?from)) )) 26 | 27 | ;; loads an empty robot with a container held by a nearby crane 28 | (:action load 29 | :parameters (?l - location ?c - container ?r - robot) 30 | :precondition (and (atl ?r ?l) (in ?c ?l) (unloaded ?r)) 31 | :effect (and (loaded ?r ?c) 32 | (not (in ?c ?l)) (not (unloaded ?r)) )) 33 | 34 | ;; unloads a robot holding a container with a nearby crane 35 | (:action unload 36 | :parameters (?l - location ?c - container ?r - robot) 37 | :precondition (and (atl ?r ?l) (loaded ?r ?c) ) 38 | :effect (and (unloaded ?r) (in ?c ?l) 39 | (not (loaded ?r ?c)) )) ) 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # planning-graph 2 | Planning Graph for AI Planning in Python 3 | 4 | ## About 5 | This library implements Planning Graph and its Planner that can be used to solve 6 | STRIPS-like AI Planning Problems using PDDL. 7 | 8 | When passed the domain and problem representations in PDDL, the library returns 9 | Solution Plan if any. 10 | 11 | ## Documentation 12 | If you are interested in understanding the Planning Graph, please read my post 13 | at https://towardsdatascience.com/improving-classical-ai-planning-complexity-with-planning-graph-c63d47f87018 14 | 15 | ## Installation 16 | ```commandline 17 | pip install planning-graph 18 | ``` 19 | or, you can clone this repository 20 | 21 | ## Example 22 | 23 | ### PDDL for representing planning domain and problem 24 | The Dock-Worker Robots Domain and Problem are provided in the [domain](domain) directory. 25 | You can create your own PDDL files, or you can download from the internet. 26 | 27 | ### Create a Planning Graph from PDDL 28 | ```python 29 | from planning_graph.planning_graph import PlanningGraph 30 | 31 | 32 | planning_graph = PlanningGraph('domain/dock-worker-robot-domain.pddl', 33 | 'domain/dock-worker-robot-problem.pddl') 34 | 35 | graph = planning_graph.create(max_num_of_levels=10) 36 | ``` 37 | planning_graph.create() returns a Graph object if the goal state is achieved, or 38 | the maximum number of levels have been reached. 39 | 40 | ### Create visualization 41 | If you want to visualize the generated graph you can set visualize=True, by default 42 | it is set to False. 43 | ```python 44 | from planning_graph.planning_graph import PlanningGraph 45 | 46 | 47 | planning_graph = PlanningGraph('domain/dock-worker-robot-domain.pddl', 48 | 'domain/dock-worker-robot-problem.pddl', 49 | visualize=True) 50 | 51 | graph = planning_graph.create(max_num_of_levels=10) 52 | graph.visualize_png("generated_graph.png") 53 | ``` 54 | the result looks like the following: 55 | ![alt text](domain/planning_graph.png) 56 | 57 | ### Find a Solution Plan 58 | To find a solution plan you simply have to create a Planner and pass the arguments 59 | it requires. 60 | ```python 61 | from planning_graph.planning_graph import PlanningGraph 62 | from planning_graph.planning_graph_planner import GraphPlanner 63 | 64 | 65 | planning_graph = PlanningGraph('domain/dock-worker-robot-domain.pddl', 66 | 'domain/dock-worker-robot-problem.pddl') 67 | 68 | graph = planning_graph.create(max_num_of_levels=10) 69 | goal = planning_graph.goal 70 | graph_planner = GraphPlanner() 71 | layered_plan = graph_planner.plan(graph, goal) 72 | ``` 73 | it returns a layered plan if the solution exists, otherwise, it returns None. 74 | 75 | ## pddlpy 76 | pddlpy included in this repo is the work of Hernán M. Foffani, it is copied from [here.](https://github.com/hfoffani/pddl-lib) 77 | It is copied because it won't work when installed as a package due to wrong version of 78 | antlr4 package. There are no changes made to it. 79 | -------------------------------------------------------------------------------- /tests/test_planning_graph.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from planning_graph.planning_graph import PlanningGraph, Plan, LayeredPlan, \ 4 | NoOpAction, Graph 5 | from pddlpy import Operator 6 | 7 | 8 | class TestPlan: 9 | 10 | def test_constructor(self): 11 | op1 = Operator("op1") 12 | op2 = Operator("op2") 13 | expected_plan = [op1, op2] 14 | plan = Plan() 15 | plan.append(op1) 16 | plan.append(op2) 17 | assert plan.plan == expected_plan 18 | 19 | 20 | class TestLayeredPlan: 21 | 22 | def test_constructor(self): 23 | op1 = Operator("op1") 24 | op2 = Operator("op2") 25 | plan = Plan() 26 | plan.append(op1) 27 | plan.append(op2) 28 | layered_plan = LayeredPlan() 29 | layered_plan[0] = plan 30 | 31 | assert layered_plan[0] == plan 32 | assert layered_plan.data[0] == plan 33 | 34 | 35 | class TestNoOpAction: 36 | 37 | def test_dummy_action(self): 38 | data = (1, 2, 3) 39 | noop = NoOpAction(data) 40 | assert noop.precondition_pos == noop.effect_pos 41 | assert noop.precondition_neg == set() 42 | assert noop.effect_neg == set() 43 | 44 | 45 | class TestGraph: 46 | 47 | def test_constructor(self): 48 | graph = Graph() 49 | assert graph.fixed_point is False 50 | assert graph.visualize is False 51 | assert graph.act[0] is None 52 | assert graph.act_mutexes[0] is None 53 | assert graph.prop_mutexes[0] is None 54 | 55 | 56 | class TestPlanningGraph: 57 | 58 | def test_create(self): 59 | planning_graph = PlanningGraph( 60 | 'domain/dock-worker-robot-domain.pddl', 61 | 'domain/dock-worker-robot-problem.pddl') 62 | graph = planning_graph.create(max_num_of_levels=10) 63 | assert graph.num_of_levels == 4 64 | assert graph.fixed_point is False 65 | 66 | def test_expand(self): 67 | planning_graph = PlanningGraph( 68 | 'domain/dock-worker-robot-domain.pddl', 69 | 'domain/dock-worker-robot-problem.pddl') 70 | graph = planning_graph.create(max_num_of_levels=2) 71 | assert graph.num_of_levels == 2 72 | assert graph.fixed_point is False 73 | graph = planning_graph.expand(graph) 74 | assert graph.num_of_levels == 3 75 | assert graph.fixed_point is False 76 | 77 | def test_expand_fixed(self): 78 | planning_graph = PlanningGraph( 79 | 'domain/dock-worker-robot-domain.pddl', 80 | 'domain/dock-worker-robot-problem.pddl') 81 | graph = planning_graph.create(max_num_of_levels=4) 82 | assert graph.num_of_levels == 4 83 | assert graph.fixed_point is False 84 | graph = planning_graph.expand(graph) 85 | assert graph.num_of_levels == 5 86 | assert graph.fixed_point is True 87 | 88 | def test_expand_invalid(self): 89 | planning_graph = PlanningGraph( 90 | 'domain/dock-worker-robot-domain.pddl', 91 | 'domain/dock-worker-robot-problem.pddl') 92 | graph = Graph() 93 | with pytest.raises(ValueError): 94 | planning_graph.expand(graph) 95 | -------------------------------------------------------------------------------- /planning_graph/pddl_adapter.py: -------------------------------------------------------------------------------- 1 | """PDDL Adapter 2 | 3 | Description: 4 | The adaptation layer (wrapper) of pddlpy module. 5 | 6 | License: 7 | Copyright 2021 Debby Nirwan 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | """ 21 | from pddlpy import DomainProblem, Operator, Atom 22 | from typing import Set, Tuple, List 23 | import itertools 24 | 25 | 26 | class PlanningProblem(object): 27 | 28 | def __init__(self, dom_file: str, problem_file: str): 29 | self._domain_file = dom_file 30 | self._problem_file = problem_file 31 | self._domain_problem = DomainProblem(self._domain_file, 32 | self._problem_file) 33 | self._initial_state = self._to_set_of_tuples(self._domain_problem. 34 | initialstate()) 35 | self._goal_state = self._to_set_of_tuples(self._domain_problem.goals()) 36 | self._actions = self._get_ground_operators() 37 | 38 | @staticmethod 39 | def _type_symbols(variable_type, world_objects: dict): 40 | # if variable type is found in the world objects, 41 | # return list of object names, such as robr, robq 42 | return (k for k, v in world_objects.items() if v == variable_type) 43 | 44 | def _instantiate(self, variables, world_objects: dict): 45 | variable_ground_space = [] 46 | for variable_name, variable_type in variables: 47 | c = [] 48 | for symbol in self._type_symbols(variable_type, world_objects): 49 | c.append((variable_name, symbol)) 50 | variable_ground_space.append(c) 51 | return itertools.product(*variable_ground_space) 52 | 53 | def _get_ground_operators(self) -> List[Operator]: 54 | ground_operators = [] 55 | for operator in self._domain_problem.operators(): 56 | op = self._domain_problem.domain.operators[operator] 57 | for ground in self._instantiate(op.variable_list.items(), 58 | self._domain_problem. 59 | worldobjects()): 60 | st = dict(ground) 61 | gop = Operator(operator) 62 | gop.variable_list = st 63 | gop.precondition_pos = set( 64 | [a.ground(st) for a in op.precondition_pos]) 65 | gop.precondition_neg = set( 66 | [a.ground(st) for a in op.precondition_neg]) 67 | gop.effect_pos = set([a.ground(st) for a in op.effect_pos]) 68 | gop.effect_neg = set([a.ground(st) for a in op.effect_neg]) 69 | ground_operators.append(gop) 70 | return ground_operators 71 | 72 | @staticmethod 73 | def _to_set_of_tuples(state: Set[Atom]) -> Set[Tuple]: 74 | set_of_tuples = set() 75 | for atom in state: 76 | tup = tuple(atom.predicate) 77 | set_of_tuples.add(tup) 78 | return set_of_tuples 79 | 80 | @property 81 | def initial_state(self): 82 | return self._initial_state 83 | 84 | @property 85 | def goal_state(self): 86 | return self._goal_state 87 | 88 | @property 89 | def actions(self): 90 | return self._actions 91 | -------------------------------------------------------------------------------- /planning_graph/planning_graph_planner.py: -------------------------------------------------------------------------------- 1 | """Planning Graph Planner 2 | 3 | Description: 4 | The planner - search algorithm to find solution plan in Planning Graph. 5 | 6 | License: 7 | Copyright 2021 Debby Nirwan 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | """ 21 | from .planning_graph import Graph, LayeredPlan, Plan, PlanningGraph 22 | from typing import Optional 23 | 24 | 25 | class GraphPlanner(object): 26 | 27 | def __init__(self): 28 | self._layered_plan: LayeredPlan = LayeredPlan() 29 | self._mutex = {} 30 | 31 | def plan(self, gr: Graph, g: set): 32 | index = gr.num_of_levels - 1 33 | 34 | if not g.issubset(gr.prop[index]): 35 | return None 36 | 37 | plan = self._extract(gr, g, index) 38 | if plan: 39 | return self._layered_plan 40 | 41 | if gr.fixed_point: 42 | n = 0 43 | try: 44 | props_mutex = self._mutex[gr.num_of_levels - 1] 45 | except KeyError: 46 | props_mutex = None 47 | if props_mutex: 48 | n = len(props_mutex) 49 | else: 50 | n = 0 51 | 52 | while True: 53 | index += 1 54 | gr = PlanningGraph.expand(gr) 55 | plan = self._extract(gr, g, index) 56 | if plan: 57 | return self._layered_plan 58 | elif gr.fixed_point: 59 | try: 60 | props_mutex = self._mutex[gr.num_of_levels-1] 61 | except KeyError: 62 | props_mutex = None 63 | if props_mutex: 64 | if n == len(props_mutex): 65 | # this means that it has stabilised 66 | return None 67 | else: 68 | n = len(props_mutex) 69 | 70 | def _extract(self, gr: Graph, g: set, index: int) -> Optional[Plan]: 71 | if index == 0: 72 | return Plan() 73 | return self._search(gr, g, Plan(), index) 74 | 75 | def _search(self, gr: Graph, g: set, plan: Plan, index: int): 76 | if g == set(): 77 | new_goals = set() 78 | for action in plan.plan: 79 | for proposition in action.precondition_pos: 80 | if 'adjacent' not in proposition: 81 | new_goals.add(proposition) 82 | 83 | extracted_plan = self._extract(gr, new_goals, index-1) 84 | if extracted_plan is None: 85 | return None 86 | else: 87 | self._layered_plan[index-1] = extracted_plan 88 | self._layered_plan[index] = plan 89 | return plan 90 | else: 91 | # select any p in g 92 | proposition = g.pop() 93 | 94 | # compute resolvers 95 | resolvers = [] 96 | for action in gr.act[index]: 97 | if proposition in action.effect_pos: 98 | if plan.plan: 99 | mutex = False 100 | for action2 in plan.plan: 101 | if (action, action2) in \ 102 | gr.act_mutexes[index]: 103 | mutex = True 104 | break 105 | if not mutex: 106 | resolvers.append(action) 107 | else: 108 | resolvers.append(action) 109 | 110 | # no resolvers 111 | if not resolvers: 112 | return None 113 | 114 | # choose non-deterministically and backtrack if failed 115 | while resolvers: 116 | resolver = resolvers.pop() 117 | plan.append(resolver) 118 | plan_result = self._search(gr, g - resolver.effect_pos, 119 | plan, index) 120 | if plan_result is not None: 121 | return plan_result 122 | else: 123 | plan.remove(resolver) 124 | g.add(proposition) 125 | return None 126 | -------------------------------------------------------------------------------- /planning_graph/planning_graph.py: -------------------------------------------------------------------------------- 1 | """Planning Graph 2 | 3 | Description: 4 | This module is responsible in creating and expanding Planning Graph. 5 | 6 | License: 7 | Copyright 2021 Debby Nirwan 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | """ 21 | from .pddl_adapter import PlanningProblem 22 | from pddlpy import Operator 23 | from typing import List, Set, Tuple, Dict, Optional 24 | from itertools import permutations 25 | import pydot 26 | 27 | 28 | class Plan(object): 29 | 30 | def __init__(self): 31 | self._plan: List[Operator] = [] 32 | 33 | def __eq__(self, other): 34 | if self._plan == other.plan: 35 | return True 36 | else: 37 | return False 38 | 39 | def __ne__(self, other): 40 | return not self.__eq__(other) 41 | 42 | def __repr__(self): 43 | return f"Plan object. {self._plan}" 44 | 45 | def append(self, action: Operator): 46 | self._plan.append(action) 47 | 48 | def remove(self, action: Operator): 49 | self._plan.remove(action) 50 | 51 | @property 52 | def plan(self): 53 | return self._plan 54 | 55 | 56 | class LayeredPlan(object): 57 | 58 | def __init__(self): 59 | self._layered_plan: Dict[int, Plan] = {} 60 | 61 | def __setitem__(self, key, value): 62 | self._layered_plan[key] = value 63 | 64 | def __getitem__(self, key): 65 | try: 66 | value = self._layered_plan[key] 67 | except KeyError: 68 | value = None 69 | return value 70 | 71 | def __repr__(self): 72 | return f"LayeredPlan. Levels={len(self._layered_plan)}" 73 | 74 | @property 75 | def data(self): 76 | return self._layered_plan 77 | 78 | 79 | class NoOpAction(Operator): 80 | 81 | def __init__(self, atom: tuple, name="NoOp"): 82 | super().__init__(name) 83 | self.precondition_pos.add(atom) 84 | self.effect_pos.add(atom) 85 | 86 | def __repr__(self): 87 | return f"NoOp Action. Preconds={self.precondition_pos}, Effects=" \ 88 | f"{self.effect_pos}" 89 | 90 | 91 | class Graph(object): 92 | 93 | def __init__(self, visualize=False): 94 | self.num_of_levels: int = 0 95 | self.act = {} 96 | self.act_mutexes = {} 97 | self.prop = {} 98 | self.prop_mutexes = {} 99 | self.fixed_point = False 100 | self.visualize = visualize 101 | self.dot = pydot.Dot(graph_type="digraph", rankdir="LR") 102 | self._init() 103 | 104 | def __repr__(self): 105 | return f"Planning Graph object with {self.num_of_levels} levels" 106 | 107 | def _init(self): 108 | self.act = {0: None} 109 | self.act_mutexes = {0: None} 110 | self.prop_mutexes = {0: None} 111 | 112 | def visualize_png(self, filename='planning_graph.png'): 113 | if self.visualize: 114 | self.dot.write_png(filename) 115 | 116 | 117 | class PlanningGraph(object): 118 | 119 | def __init__(self, dom_file: str, problem_file: str, visualize=False): 120 | self._planning_problem = PlanningProblem(dom_file, problem_file) 121 | self._graph: Graph = Graph(visualize) 122 | 123 | def create(self, max_num_of_levels=10): 124 | self._graph.prop = {0: self._planning_problem.initial_state} 125 | self._graph.num_of_levels = 1 126 | 127 | for level in range(1, max_num_of_levels): 128 | self._graph = self.expand(self._graph) 129 | 130 | goal_set = self._planning_problem.goal_state 131 | index = self._graph.num_of_levels - 1 132 | proposition_list = self._graph.prop[index] 133 | proposition_mutex_list = self._graph.prop_mutexes[index] 134 | if goal_set.issubset(proposition_list): 135 | # goals in proposition list and 136 | # goals not in mutex proposition list 137 | goal_found = True 138 | for goal_pair in list(permutations(goal_set, 2)): 139 | if goal_pair in proposition_mutex_list: 140 | goal_found = False 141 | break 142 | if goal_found: 143 | break 144 | elif index > 0 and self._graph.prop[index-1] == proposition_list: 145 | self._graph.fixed_point = True 146 | break 147 | 148 | return self._graph 149 | 150 | def expand(self, gr: Graph) -> Graph: 151 | graph_result = gr 152 | level = gr.num_of_levels 153 | 154 | if level <= 0: 155 | raise ValueError("Input Graph should not be empty") 156 | 157 | # Compute Ai 158 | action_list = [] 159 | for action in self._planning_problem.actions: 160 | if self._applicable(action, graph_result.prop[level - 1], 161 | graph_result.prop_mutexes[level - 1]): 162 | action_list.append(action) 163 | for proposition in graph_result.prop[level - 1]: 164 | action_list.append(NoOpAction(proposition)) 165 | graph_result.act[level] = action_list 166 | if graph_result.visualize: 167 | edge = pydot.Edge(self.beautify_state( 168 | graph_result.prop[level - 1]), 169 | self.beautify_state(graph_result.act[level]), ) 170 | graph_result.dot.add_edge(edge) 171 | 172 | # Compute Pi 173 | proposition_list = set() 174 | for action in action_list: 175 | for effect in action.effect_pos: 176 | proposition_list.add(effect) 177 | graph_result.prop[level] = proposition_list 178 | if graph_result.visualize: 179 | edge = pydot.Edge(self.beautify_state(graph_result.act[level]), 180 | self.beautify_state(graph_result.prop[level])) 181 | graph_result.dot.add_edge(edge) 182 | 183 | # Compute mutex Ai 184 | action_mutex_list = [] 185 | for action_pair in list(permutations(action_list, 2)): 186 | if self.compute_mutex_action(action_pair, 187 | graph_result.prop_mutexes[level - 1]): 188 | action_mutex_list.append(action_pair) 189 | graph_result.act_mutexes[level] = action_mutex_list 190 | 191 | # Compute mutex Pi 192 | proposition_mutex_list = [] 193 | for proposition_pair in list(permutations(proposition_list, 2)): 194 | if self.compute_mutex_precondition(proposition_pair, 195 | action_list, 196 | action_mutex_list): 197 | if proposition_pair not in proposition_mutex_list: 198 | swapped = (proposition_pair[1], proposition_pair[0]) 199 | if swapped not in proposition_mutex_list: 200 | proposition_mutex_list.append(proposition_pair) 201 | graph_result.prop_mutexes[level] = proposition_mutex_list 202 | 203 | # update number of levels 204 | graph_result.num_of_levels = level + 1 205 | if graph_result.prop[level - 1] == proposition_list: 206 | graph_result.fixed_point = True 207 | 208 | return graph_result 209 | 210 | @staticmethod 211 | def beautify_state(state) -> str: 212 | """set of tuples to multiple lines of string""" 213 | final_string = str() 214 | for atom in state: 215 | if isinstance(atom, NoOpAction): 216 | pass 217 | elif isinstance(atom, Operator): 218 | atom_string = atom.operator_name + ": " + str(atom.effect_pos) 219 | final_string += atom_string + '\n' 220 | else: 221 | atom_string = str(atom) 222 | final_string += atom_string + '\n' 223 | return final_string 224 | 225 | @staticmethod 226 | def compute_mutex_action(pair: tuple, 227 | preconds_mutex: List[Tuple[Tuple]]) -> bool: 228 | a = pair[0] 229 | b = pair[1] 230 | 231 | # two actions are dependent 232 | if a.effect_neg.intersection(b.precondition_pos.union(b.effect_pos)) \ 233 | != set(): 234 | return True 235 | if b.effect_neg.intersection(a.precondition_pos.union(a.effect_pos)) \ 236 | != set(): 237 | return True 238 | 239 | # their preconditions are mutex 240 | if preconds_mutex is not None: 241 | for mutex in preconds_mutex: 242 | # (p, q) 243 | p = mutex[0] 244 | q = mutex[1] 245 | if p in a.precondition_pos and q in b.precondition_pos: 246 | return True 247 | 248 | return False 249 | 250 | @staticmethod 251 | def compute_mutex_precondition(proposition_pair, action_list, 252 | action_mutex): 253 | p = proposition_pair[0] 254 | q = proposition_pair[1] 255 | 256 | for action in action_list: 257 | if p in action.effect_pos and q in action.effect_pos: 258 | # (p, q) are not mutex if they both are produced by the 259 | # same action 260 | return False 261 | 262 | # every action that produces p 263 | actions_with_p = set() 264 | for action in action_list: 265 | if p in action.effect_pos: 266 | actions_with_p.add(action) 267 | 268 | # every action that produces q 269 | actions_with_q = set() 270 | for action in action_list: 271 | if q in action.effect_pos: 272 | actions_with_q.add(action) 273 | 274 | all_mutex = True 275 | for p_action in actions_with_p: 276 | for q_action in actions_with_q: 277 | if p_action == q_action: 278 | return False 279 | if (p_action, q_action) not in action_mutex: 280 | all_mutex = False 281 | break 282 | if not all_mutex: 283 | break 284 | 285 | return all_mutex 286 | 287 | @staticmethod 288 | def _applicable(action: Operator, state: Set[Tuple], 289 | preconditions_mutex: Optional[List[Tuple[Tuple]]]) -> bool: 290 | if action.precondition_pos.issubset(state) and \ 291 | action.precondition_neg.isdisjoint(state): 292 | applicable = True 293 | if preconditions_mutex is not None: 294 | for precondition in list(permutations(action.precondition_pos, 295 | 2)): 296 | if precondition in preconditions_mutex: 297 | applicable = False 298 | break 299 | else: 300 | applicable = False 301 | 302 | return applicable 303 | 304 | @property 305 | def initial_state(self): 306 | return self._planning_problem.initial_state 307 | 308 | @property 309 | def goal(self): 310 | return self._planning_problem.goal_state 311 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /pddlpy/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2015 Hernán M. Foffani 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /pddlpy/pddl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # 5 | # Copyright 2015 Hernán M. Foffani 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | # 20 | 21 | from antlr4 import * 22 | from .pddlLexer import pddlLexer 23 | from .pddlParser import pddlParser 24 | from .pddlListener import pddlListener 25 | 26 | import itertools 27 | 28 | 29 | class Atom(): 30 | def __init__(self, predicate): 31 | self.predicate = predicate 32 | 33 | def __repr__(self): 34 | return str(tuple(self.predicate)) 35 | 36 | def ground(self, varvals): 37 | g = [ varvals[v] if v in varvals else v for v in self.predicate ] 38 | return tuple(g) 39 | 40 | class Scope(): 41 | def __init__(self): 42 | self.atoms = [] 43 | self.negatoms = [] 44 | 45 | def addatom(self, atom): 46 | self.atoms.append(atom) 47 | 48 | def addnegatom(self, atom): 49 | self.negatoms.append(atom) 50 | 51 | 52 | class Obj(): 53 | def __init__(self): 54 | self.variable_list = {} 55 | 56 | class Operator(): 57 | """Represents and action. Can be grounded or ungrounded. 58 | Ungrounded operators have a '?' in names (unbound variables). 59 | Attributes: 60 | 61 | operator_name -- the name of operator (action in the domain.) 62 | variable_list -- a dictionary of key-value pairs where the key 63 | is the variable name (with the '?') and the 64 | value is the value of it when the operator is 65 | grounded. 66 | precondition_pos -- a set of atoms corresponding to the 67 | positive preconditions. 68 | precondition_neg -- a set of atoms corresponding to the 69 | negative preconditions. 70 | effect_pos -- a set of atoms to add. 71 | effect_neg -- a set of atoms to delete. 72 | """ 73 | def __init__(self, name): 74 | self.operator_name = name 75 | self.variable_list = {} 76 | self.precondition_pos = set() 77 | self.precondition_neg = set() 78 | self.effect_pos = set() 79 | self.effect_neg = set() 80 | 81 | 82 | class DomainListener(pddlListener): 83 | def __init__(self): 84 | self.typesdef = False 85 | self.objects = {} 86 | self.operators = {} 87 | self.scopes = [] 88 | self.negativescopes = [] 89 | 90 | def enterActionDef(self, ctx): 91 | opname = ctx.actionSymbol().getText() 92 | opvars = {} 93 | self.scopes.append(Operator(opname)) 94 | 95 | def exitActionDef(self, ctx): 96 | action = self.scopes.pop() 97 | self.operators[action.operator_name] = action 98 | 99 | def enterPredicatesDef(self, ctx): 100 | self.scopes.append(Operator(None)) 101 | 102 | def exitPredicatesDef(self, ctx): 103 | dummyop = self.scopes.pop() 104 | 105 | def enterTypesDef(self, ctx): 106 | self.scopes.append(Obj()) 107 | 108 | def exitTypesDef(self, ctx): 109 | self.typesdef = True 110 | self.scopes.pop() 111 | 112 | def enterTypedVariableList(self, ctx): 113 | # print("-> tvar") 114 | for v in ctx.VARIABLE(): 115 | vname = v.getText() 116 | self.scopes[-1].variable_list[v.getText()] = None 117 | for vs in ctx.singleTypeVarList(): 118 | t = vs.r_type().getText() 119 | for v in vs.VARIABLE(): 120 | vname = v.getText() 121 | self.scopes[-1].variable_list[vname] = t 122 | 123 | def enterAtomicTermFormula(self, ctx): 124 | # print("-> terf") 125 | neg = self.negativescopes[-1] 126 | pred = [] 127 | for c in ctx.getChildren(): 128 | n = c.getText() 129 | if n == '(' or n == ')': 130 | continue 131 | pred.append(n) 132 | scope = self.scopes[-1] 133 | if not neg: 134 | scope.addatom(Atom(pred)) 135 | else: 136 | scope.addnegatom(Atom(pred)) 137 | 138 | def enterPrecondition(self, ctx): 139 | self.scopes.append(Scope()) 140 | 141 | def exitPrecondition(self, ctx): 142 | scope = self.scopes.pop() 143 | self.scopes[-1].precondition_pos = set( scope.atoms ) 144 | self.scopes[-1].precondition_neg = set( scope.negatoms ) 145 | 146 | def enterEffect(self, ctx): 147 | self.scopes.append(Scope()) 148 | 149 | def exitEffect(self, ctx): 150 | scope = self.scopes.pop() 151 | self.scopes[-1].effect_pos = set( scope.atoms ) 152 | self.scopes[-1].effect_neg = set( scope.negatoms ) 153 | 154 | def enterGoalDesc(self, ctx): 155 | negscope = bool(self.negativescopes and self.negativescopes[-1]) 156 | for c in ctx.getChildren(): 157 | if c.getText() == 'not': 158 | negscope = True 159 | break 160 | self.negativescopes.append(negscope) 161 | 162 | def exitGoalDesc(self, ctx): 163 | self.negativescopes.pop() 164 | 165 | def enterPEffect(self, ctx): 166 | negscope = False 167 | for c in ctx.getChildren(): 168 | if c.getText() == 'not': 169 | negscope = True 170 | break 171 | self.negativescopes.append(negscope) 172 | 173 | def exitPEffect(self, ctx): 174 | self.negativescopes.pop() 175 | 176 | def enterTypedNameList(self, ctx): 177 | # print("-> tnam") 178 | for v in ctx.name(): 179 | vname = v.getText() 180 | self.scopes[-1].variable_list[v.getText()] = None 181 | for vs in ctx.singleTypeNameList(): 182 | t = vs.r_type().getText() 183 | for v in vs.name(): 184 | vname = v.getText() 185 | self.scopes[-1].variable_list[vname] = t 186 | 187 | def enterConstantsDef(self, ctx): 188 | self.scopes.append(Obj()) 189 | 190 | def exitConstantsDef(self, ctx): 191 | scope = self.scopes.pop() 192 | self.objects = scope.variable_list 193 | 194 | def exitDomain(self, ctx): 195 | if not self.objects and not self.typesdef: 196 | vs = set() 197 | for opn, oper in self.operators.items(): 198 | alls = oper.precondition_pos | oper.precondition_neg | oper.effect_pos | oper.effect_neg 199 | for a in alls: 200 | for s in a.predicate: 201 | if s[0] != '?': 202 | vs.add( (s, None) ) 203 | self.objects = dict( vs) 204 | 205 | 206 | class ProblemListener(pddlListener): 207 | 208 | def __init__(self): 209 | self.objects = {} 210 | self.initialstate = [] 211 | self.goals = [] 212 | self.scopes = [] 213 | 214 | def enterInit(self, ctx): 215 | self.scopes.append(Scope()) 216 | 217 | def exitInit(self, ctx): 218 | self.initialstate = set( self.scopes.pop().atoms ) 219 | 220 | def enterGoal(self, ctx): 221 | self.scopes.append(Scope()) 222 | 223 | def exitGoal(self, ctx): 224 | self.goals = set( self.scopes.pop().atoms ) 225 | 226 | def enterAtomicNameFormula(self, ctx): 227 | pred = [] 228 | for c in ctx.getChildren(): 229 | n = c.getText() 230 | if n == '(' or n == ')': 231 | continue 232 | pred.append(n) 233 | scope = self.scopes[-1] 234 | scope.addatom(Atom(pred)) 235 | 236 | def enterAtomicTermFormula(self, ctx): 237 | # with a NOT! 238 | pred = [] 239 | for c in ctx.getChildren(): 240 | n = c.getText() 241 | if n == '(' or n == ')': 242 | continue 243 | pred.append(n) 244 | scope = self.scopes[-1] 245 | scope.addatom(Atom(pred)) 246 | 247 | def enterTypedNameList(self, ctx): 248 | for v in ctx.name(): 249 | vname = v.getText() 250 | self.scopes[-1].variable_list[v.getText()] = None 251 | for vs in ctx.singleTypeNameList(): 252 | t = vs.r_type().getText() 253 | for v in vs.name(): 254 | vname = v.getText() 255 | self.scopes[-1].variable_list[vname] = t 256 | 257 | def enterObjectDecl(self, ctx): 258 | self.scopes.append(Obj()) 259 | 260 | def exitObjectDecl(self, ctx): 261 | scope = self.scopes.pop() 262 | self.objects = scope.variable_list 263 | 264 | def exitProblem(self, ctx): 265 | if not self.objects: 266 | vs = set() 267 | for a in self.initialstate: 268 | for s in a.predicate: 269 | vs.add( (s, None) ) 270 | for a in self.goals: 271 | for s in a.predicate: 272 | vs.add( (s, None) ) 273 | self.objects = dict( vs ) 274 | 275 | 276 | class DomainProblem(): 277 | 278 | def __init__(self, domainfile, problemfile): 279 | """Parses a PDDL domain and problem files and 280 | returns an object representing them. 281 | 282 | domainfile -- path for the PDDL domain file 283 | problemfile -- path for the PDDL problem file 284 | """ 285 | # domain 286 | inp = FileStream(domainfile) 287 | lexer = pddlLexer(inp) 288 | stream = CommonTokenStream(lexer) 289 | parser = pddlParser(stream) 290 | tree = parser.domain() 291 | self.domain = DomainListener() 292 | walker = ParseTreeWalker() 293 | walker.walk(self.domain, tree) 294 | # problem 295 | inp = FileStream(problemfile) 296 | lexer = pddlLexer(inp) 297 | stream = CommonTokenStream(lexer) 298 | parser = pddlParser(stream) 299 | tree = parser.problem() 300 | self.problem = ProblemListener() 301 | walker = ParseTreeWalker() 302 | walker.walk(self.problem, tree) 303 | # variable ground space 304 | self.vargroundspace = [] 305 | 306 | def operators(self): 307 | """Returns an iterator of the names of the actions defined in 308 | the domain file. 309 | """ 310 | return self.domain.operators.keys() 311 | 312 | def ground_operator(self, op_name): 313 | """Returns an interator of Operator instances. Each item of the iterator 314 | is a grounded instance. 315 | 316 | returns -- An iterator of Operator instances. 317 | """ 318 | op = self.domain.operators[op_name] 319 | for ground in self._instantiate( op.variable_list.items() ): 320 | st = dict(ground) 321 | gop = Operator(op_name) 322 | gop.variable_list = st 323 | gop.precondition_pos = set( [ a.ground( st ) for a in op.precondition_pos ] ) 324 | gop.precondition_neg = set( [ a.ground( st ) for a in op.precondition_neg ] ) 325 | gop.effect_pos = set( [ a.ground( st ) for a in op.effect_pos ] ) 326 | gop.effect_neg = set( [ a.ground( st ) for a in op.effect_neg ] ) 327 | yield gop 328 | 329 | def _typesymbols(self, t): 330 | return ( k for k,v in self.worldobjects().items() if v == t ) 331 | 332 | def _instantiate(self, variables): 333 | if not self.vargroundspace: 334 | for vname, t in variables: 335 | c = [] 336 | for symb in self._typesymbols(t): 337 | c.append((vname, symb) ) 338 | self.vargroundspace.append(c) 339 | return itertools.product(*self.vargroundspace) 340 | 341 | def initialstate(self): 342 | """Returns a set of atoms (tuples of strings) corresponding to the intial 343 | state defined in the problem file. 344 | """ 345 | return self.problem.initialstate 346 | 347 | def goals(self): 348 | """Returns a set of atoms (tuples of strings) corresponding to the goals 349 | defined in the problem file. 350 | """ 351 | return self.problem.goals 352 | 353 | def worldobjects(self): 354 | """Returns a dictionary of key value pairs where the key is the name of 355 | an object and the value is it's type (None in case is untyped.) 356 | """ 357 | return dict( self.domain.objects.items() | self.problem.objects.items() ) 358 | 359 | 360 | 361 | if __name__ == '__main__': 362 | pass 363 | 364 | -------------------------------------------------------------------------------- /pddlpy/pddlListener.py: -------------------------------------------------------------------------------- 1 | # Generated from pddl.g4 by ANTLR 4.7 2 | from antlr4 import * 3 | if __name__ is not None and "." in __name__: 4 | from .pddlParser import pddlParser 5 | else: 6 | from pddlParser import pddlParser 7 | 8 | # This class defines a complete listener for a parse tree produced by pddlParser. 9 | class pddlListener(ParseTreeListener): 10 | 11 | # Enter a parse tree produced by pddlParser#pddlDoc. 12 | def enterPddlDoc(self, ctx:pddlParser.PddlDocContext): 13 | pass 14 | 15 | # Exit a parse tree produced by pddlParser#pddlDoc. 16 | def exitPddlDoc(self, ctx:pddlParser.PddlDocContext): 17 | pass 18 | 19 | 20 | # Enter a parse tree produced by pddlParser#domain. 21 | def enterDomain(self, ctx:pddlParser.DomainContext): 22 | pass 23 | 24 | # Exit a parse tree produced by pddlParser#domain. 25 | def exitDomain(self, ctx:pddlParser.DomainContext): 26 | pass 27 | 28 | 29 | # Enter a parse tree produced by pddlParser#domainName. 30 | def enterDomainName(self, ctx:pddlParser.DomainNameContext): 31 | pass 32 | 33 | # Exit a parse tree produced by pddlParser#domainName. 34 | def exitDomainName(self, ctx:pddlParser.DomainNameContext): 35 | pass 36 | 37 | 38 | # Enter a parse tree produced by pddlParser#requireDef. 39 | def enterRequireDef(self, ctx:pddlParser.RequireDefContext): 40 | pass 41 | 42 | # Exit a parse tree produced by pddlParser#requireDef. 43 | def exitRequireDef(self, ctx:pddlParser.RequireDefContext): 44 | pass 45 | 46 | 47 | # Enter a parse tree produced by pddlParser#typesDef. 48 | def enterTypesDef(self, ctx:pddlParser.TypesDefContext): 49 | pass 50 | 51 | # Exit a parse tree produced by pddlParser#typesDef. 52 | def exitTypesDef(self, ctx:pddlParser.TypesDefContext): 53 | pass 54 | 55 | 56 | # Enter a parse tree produced by pddlParser#typedNameList. 57 | def enterTypedNameList(self, ctx:pddlParser.TypedNameListContext): 58 | pass 59 | 60 | # Exit a parse tree produced by pddlParser#typedNameList. 61 | def exitTypedNameList(self, ctx:pddlParser.TypedNameListContext): 62 | pass 63 | 64 | 65 | # Enter a parse tree produced by pddlParser#singleTypeNameList. 66 | def enterSingleTypeNameList(self, ctx:pddlParser.SingleTypeNameListContext): 67 | pass 68 | 69 | # Exit a parse tree produced by pddlParser#singleTypeNameList. 70 | def exitSingleTypeNameList(self, ctx:pddlParser.SingleTypeNameListContext): 71 | pass 72 | 73 | 74 | # Enter a parse tree produced by pddlParser#r_type. 75 | def enterR_type(self, ctx:pddlParser.R_typeContext): 76 | pass 77 | 78 | # Exit a parse tree produced by pddlParser#r_type. 79 | def exitR_type(self, ctx:pddlParser.R_typeContext): 80 | pass 81 | 82 | 83 | # Enter a parse tree produced by pddlParser#primType. 84 | def enterPrimType(self, ctx:pddlParser.PrimTypeContext): 85 | pass 86 | 87 | # Exit a parse tree produced by pddlParser#primType. 88 | def exitPrimType(self, ctx:pddlParser.PrimTypeContext): 89 | pass 90 | 91 | 92 | # Enter a parse tree produced by pddlParser#functionsDef. 93 | def enterFunctionsDef(self, ctx:pddlParser.FunctionsDefContext): 94 | pass 95 | 96 | # Exit a parse tree produced by pddlParser#functionsDef. 97 | def exitFunctionsDef(self, ctx:pddlParser.FunctionsDefContext): 98 | pass 99 | 100 | 101 | # Enter a parse tree produced by pddlParser#functionList. 102 | def enterFunctionList(self, ctx:pddlParser.FunctionListContext): 103 | pass 104 | 105 | # Exit a parse tree produced by pddlParser#functionList. 106 | def exitFunctionList(self, ctx:pddlParser.FunctionListContext): 107 | pass 108 | 109 | 110 | # Enter a parse tree produced by pddlParser#atomicFunctionSkeleton. 111 | def enterAtomicFunctionSkeleton(self, ctx:pddlParser.AtomicFunctionSkeletonContext): 112 | pass 113 | 114 | # Exit a parse tree produced by pddlParser#atomicFunctionSkeleton. 115 | def exitAtomicFunctionSkeleton(self, ctx:pddlParser.AtomicFunctionSkeletonContext): 116 | pass 117 | 118 | 119 | # Enter a parse tree produced by pddlParser#functionSymbol. 120 | def enterFunctionSymbol(self, ctx:pddlParser.FunctionSymbolContext): 121 | pass 122 | 123 | # Exit a parse tree produced by pddlParser#functionSymbol. 124 | def exitFunctionSymbol(self, ctx:pddlParser.FunctionSymbolContext): 125 | pass 126 | 127 | 128 | # Enter a parse tree produced by pddlParser#functionType. 129 | def enterFunctionType(self, ctx:pddlParser.FunctionTypeContext): 130 | pass 131 | 132 | # Exit a parse tree produced by pddlParser#functionType. 133 | def exitFunctionType(self, ctx:pddlParser.FunctionTypeContext): 134 | pass 135 | 136 | 137 | # Enter a parse tree produced by pddlParser#constantsDef. 138 | def enterConstantsDef(self, ctx:pddlParser.ConstantsDefContext): 139 | pass 140 | 141 | # Exit a parse tree produced by pddlParser#constantsDef. 142 | def exitConstantsDef(self, ctx:pddlParser.ConstantsDefContext): 143 | pass 144 | 145 | 146 | # Enter a parse tree produced by pddlParser#predicatesDef. 147 | def enterPredicatesDef(self, ctx:pddlParser.PredicatesDefContext): 148 | pass 149 | 150 | # Exit a parse tree produced by pddlParser#predicatesDef. 151 | def exitPredicatesDef(self, ctx:pddlParser.PredicatesDefContext): 152 | pass 153 | 154 | 155 | # Enter a parse tree produced by pddlParser#atomicFormulaSkeleton. 156 | def enterAtomicFormulaSkeleton(self, ctx:pddlParser.AtomicFormulaSkeletonContext): 157 | pass 158 | 159 | # Exit a parse tree produced by pddlParser#atomicFormulaSkeleton. 160 | def exitAtomicFormulaSkeleton(self, ctx:pddlParser.AtomicFormulaSkeletonContext): 161 | pass 162 | 163 | 164 | # Enter a parse tree produced by pddlParser#predicate. 165 | def enterPredicate(self, ctx:pddlParser.PredicateContext): 166 | pass 167 | 168 | # Exit a parse tree produced by pddlParser#predicate. 169 | def exitPredicate(self, ctx:pddlParser.PredicateContext): 170 | pass 171 | 172 | 173 | # Enter a parse tree produced by pddlParser#typedVariableList. 174 | def enterTypedVariableList(self, ctx:pddlParser.TypedVariableListContext): 175 | pass 176 | 177 | # Exit a parse tree produced by pddlParser#typedVariableList. 178 | def exitTypedVariableList(self, ctx:pddlParser.TypedVariableListContext): 179 | pass 180 | 181 | 182 | # Enter a parse tree produced by pddlParser#singleTypeVarList. 183 | def enterSingleTypeVarList(self, ctx:pddlParser.SingleTypeVarListContext): 184 | pass 185 | 186 | # Exit a parse tree produced by pddlParser#singleTypeVarList. 187 | def exitSingleTypeVarList(self, ctx:pddlParser.SingleTypeVarListContext): 188 | pass 189 | 190 | 191 | # Enter a parse tree produced by pddlParser#constraints. 192 | def enterConstraints(self, ctx:pddlParser.ConstraintsContext): 193 | pass 194 | 195 | # Exit a parse tree produced by pddlParser#constraints. 196 | def exitConstraints(self, ctx:pddlParser.ConstraintsContext): 197 | pass 198 | 199 | 200 | # Enter a parse tree produced by pddlParser#structureDef. 201 | def enterStructureDef(self, ctx:pddlParser.StructureDefContext): 202 | pass 203 | 204 | # Exit a parse tree produced by pddlParser#structureDef. 205 | def exitStructureDef(self, ctx:pddlParser.StructureDefContext): 206 | pass 207 | 208 | 209 | # Enter a parse tree produced by pddlParser#actionDef. 210 | def enterActionDef(self, ctx:pddlParser.ActionDefContext): 211 | pass 212 | 213 | # Exit a parse tree produced by pddlParser#actionDef. 214 | def exitActionDef(self, ctx:pddlParser.ActionDefContext): 215 | pass 216 | 217 | 218 | # Enter a parse tree produced by pddlParser#actionSymbol. 219 | def enterActionSymbol(self, ctx:pddlParser.ActionSymbolContext): 220 | pass 221 | 222 | # Exit a parse tree produced by pddlParser#actionSymbol. 223 | def exitActionSymbol(self, ctx:pddlParser.ActionSymbolContext): 224 | pass 225 | 226 | 227 | # Enter a parse tree produced by pddlParser#actionDefBody. 228 | def enterActionDefBody(self, ctx:pddlParser.ActionDefBodyContext): 229 | pass 230 | 231 | # Exit a parse tree produced by pddlParser#actionDefBody. 232 | def exitActionDefBody(self, ctx:pddlParser.ActionDefBodyContext): 233 | pass 234 | 235 | 236 | # Enter a parse tree produced by pddlParser#precondition. 237 | def enterPrecondition(self, ctx:pddlParser.PreconditionContext): 238 | pass 239 | 240 | # Exit a parse tree produced by pddlParser#precondition. 241 | def exitPrecondition(self, ctx:pddlParser.PreconditionContext): 242 | pass 243 | 244 | 245 | # Enter a parse tree produced by pddlParser#goalDesc. 246 | def enterGoalDesc(self, ctx:pddlParser.GoalDescContext): 247 | pass 248 | 249 | # Exit a parse tree produced by pddlParser#goalDesc. 250 | def exitGoalDesc(self, ctx:pddlParser.GoalDescContext): 251 | pass 252 | 253 | 254 | # Enter a parse tree produced by pddlParser#fComp. 255 | def enterFComp(self, ctx:pddlParser.FCompContext): 256 | pass 257 | 258 | # Exit a parse tree produced by pddlParser#fComp. 259 | def exitFComp(self, ctx:pddlParser.FCompContext): 260 | pass 261 | 262 | 263 | # Enter a parse tree produced by pddlParser#atomicTermFormula. 264 | def enterAtomicTermFormula(self, ctx:pddlParser.AtomicTermFormulaContext): 265 | pass 266 | 267 | # Exit a parse tree produced by pddlParser#atomicTermFormula. 268 | def exitAtomicTermFormula(self, ctx:pddlParser.AtomicTermFormulaContext): 269 | pass 270 | 271 | 272 | # Enter a parse tree produced by pddlParser#term. 273 | def enterTerm(self, ctx:pddlParser.TermContext): 274 | pass 275 | 276 | # Exit a parse tree produced by pddlParser#term. 277 | def exitTerm(self, ctx:pddlParser.TermContext): 278 | pass 279 | 280 | 281 | # Enter a parse tree produced by pddlParser#durativeActionDef. 282 | def enterDurativeActionDef(self, ctx:pddlParser.DurativeActionDefContext): 283 | pass 284 | 285 | # Exit a parse tree produced by pddlParser#durativeActionDef. 286 | def exitDurativeActionDef(self, ctx:pddlParser.DurativeActionDefContext): 287 | pass 288 | 289 | 290 | # Enter a parse tree produced by pddlParser#daDefBody. 291 | def enterDaDefBody(self, ctx:pddlParser.DaDefBodyContext): 292 | pass 293 | 294 | # Exit a parse tree produced by pddlParser#daDefBody. 295 | def exitDaDefBody(self, ctx:pddlParser.DaDefBodyContext): 296 | pass 297 | 298 | 299 | # Enter a parse tree produced by pddlParser#daGD. 300 | def enterDaGD(self, ctx:pddlParser.DaGDContext): 301 | pass 302 | 303 | # Exit a parse tree produced by pddlParser#daGD. 304 | def exitDaGD(self, ctx:pddlParser.DaGDContext): 305 | pass 306 | 307 | 308 | # Enter a parse tree produced by pddlParser#prefTimedGD. 309 | def enterPrefTimedGD(self, ctx:pddlParser.PrefTimedGDContext): 310 | pass 311 | 312 | # Exit a parse tree produced by pddlParser#prefTimedGD. 313 | def exitPrefTimedGD(self, ctx:pddlParser.PrefTimedGDContext): 314 | pass 315 | 316 | 317 | # Enter a parse tree produced by pddlParser#timedGD. 318 | def enterTimedGD(self, ctx:pddlParser.TimedGDContext): 319 | pass 320 | 321 | # Exit a parse tree produced by pddlParser#timedGD. 322 | def exitTimedGD(self, ctx:pddlParser.TimedGDContext): 323 | pass 324 | 325 | 326 | # Enter a parse tree produced by pddlParser#timeSpecifier. 327 | def enterTimeSpecifier(self, ctx:pddlParser.TimeSpecifierContext): 328 | pass 329 | 330 | # Exit a parse tree produced by pddlParser#timeSpecifier. 331 | def exitTimeSpecifier(self, ctx:pddlParser.TimeSpecifierContext): 332 | pass 333 | 334 | 335 | # Enter a parse tree produced by pddlParser#interval. 336 | def enterInterval(self, ctx:pddlParser.IntervalContext): 337 | pass 338 | 339 | # Exit a parse tree produced by pddlParser#interval. 340 | def exitInterval(self, ctx:pddlParser.IntervalContext): 341 | pass 342 | 343 | 344 | # Enter a parse tree produced by pddlParser#derivedDef. 345 | def enterDerivedDef(self, ctx:pddlParser.DerivedDefContext): 346 | pass 347 | 348 | # Exit a parse tree produced by pddlParser#derivedDef. 349 | def exitDerivedDef(self, ctx:pddlParser.DerivedDefContext): 350 | pass 351 | 352 | 353 | # Enter a parse tree produced by pddlParser#fExp. 354 | def enterFExp(self, ctx:pddlParser.FExpContext): 355 | pass 356 | 357 | # Exit a parse tree produced by pddlParser#fExp. 358 | def exitFExp(self, ctx:pddlParser.FExpContext): 359 | pass 360 | 361 | 362 | # Enter a parse tree produced by pddlParser#fExp2. 363 | def enterFExp2(self, ctx:pddlParser.FExp2Context): 364 | pass 365 | 366 | # Exit a parse tree produced by pddlParser#fExp2. 367 | def exitFExp2(self, ctx:pddlParser.FExp2Context): 368 | pass 369 | 370 | 371 | # Enter a parse tree produced by pddlParser#fHead. 372 | def enterFHead(self, ctx:pddlParser.FHeadContext): 373 | pass 374 | 375 | # Exit a parse tree produced by pddlParser#fHead. 376 | def exitFHead(self, ctx:pddlParser.FHeadContext): 377 | pass 378 | 379 | 380 | # Enter a parse tree produced by pddlParser#effect. 381 | def enterEffect(self, ctx:pddlParser.EffectContext): 382 | pass 383 | 384 | # Exit a parse tree produced by pddlParser#effect. 385 | def exitEffect(self, ctx:pddlParser.EffectContext): 386 | pass 387 | 388 | 389 | # Enter a parse tree produced by pddlParser#cEffect. 390 | def enterCEffect(self, ctx:pddlParser.CEffectContext): 391 | pass 392 | 393 | # Exit a parse tree produced by pddlParser#cEffect. 394 | def exitCEffect(self, ctx:pddlParser.CEffectContext): 395 | pass 396 | 397 | 398 | # Enter a parse tree produced by pddlParser#pEffect. 399 | def enterPEffect(self, ctx:pddlParser.PEffectContext): 400 | pass 401 | 402 | # Exit a parse tree produced by pddlParser#pEffect. 403 | def exitPEffect(self, ctx:pddlParser.PEffectContext): 404 | pass 405 | 406 | 407 | # Enter a parse tree produced by pddlParser#condEffect. 408 | def enterCondEffect(self, ctx:pddlParser.CondEffectContext): 409 | pass 410 | 411 | # Exit a parse tree produced by pddlParser#condEffect. 412 | def exitCondEffect(self, ctx:pddlParser.CondEffectContext): 413 | pass 414 | 415 | 416 | # Enter a parse tree produced by pddlParser#binaryOp. 417 | def enterBinaryOp(self, ctx:pddlParser.BinaryOpContext): 418 | pass 419 | 420 | # Exit a parse tree produced by pddlParser#binaryOp. 421 | def exitBinaryOp(self, ctx:pddlParser.BinaryOpContext): 422 | pass 423 | 424 | 425 | # Enter a parse tree produced by pddlParser#binaryComp. 426 | def enterBinaryComp(self, ctx:pddlParser.BinaryCompContext): 427 | pass 428 | 429 | # Exit a parse tree produced by pddlParser#binaryComp. 430 | def exitBinaryComp(self, ctx:pddlParser.BinaryCompContext): 431 | pass 432 | 433 | 434 | # Enter a parse tree produced by pddlParser#assignOp. 435 | def enterAssignOp(self, ctx:pddlParser.AssignOpContext): 436 | pass 437 | 438 | # Exit a parse tree produced by pddlParser#assignOp. 439 | def exitAssignOp(self, ctx:pddlParser.AssignOpContext): 440 | pass 441 | 442 | 443 | # Enter a parse tree produced by pddlParser#durationConstraint. 444 | def enterDurationConstraint(self, ctx:pddlParser.DurationConstraintContext): 445 | pass 446 | 447 | # Exit a parse tree produced by pddlParser#durationConstraint. 448 | def exitDurationConstraint(self, ctx:pddlParser.DurationConstraintContext): 449 | pass 450 | 451 | 452 | # Enter a parse tree produced by pddlParser#simpleDurationConstraint. 453 | def enterSimpleDurationConstraint(self, ctx:pddlParser.SimpleDurationConstraintContext): 454 | pass 455 | 456 | # Exit a parse tree produced by pddlParser#simpleDurationConstraint. 457 | def exitSimpleDurationConstraint(self, ctx:pddlParser.SimpleDurationConstraintContext): 458 | pass 459 | 460 | 461 | # Enter a parse tree produced by pddlParser#durOp. 462 | def enterDurOp(self, ctx:pddlParser.DurOpContext): 463 | pass 464 | 465 | # Exit a parse tree produced by pddlParser#durOp. 466 | def exitDurOp(self, ctx:pddlParser.DurOpContext): 467 | pass 468 | 469 | 470 | # Enter a parse tree produced by pddlParser#durValue. 471 | def enterDurValue(self, ctx:pddlParser.DurValueContext): 472 | pass 473 | 474 | # Exit a parse tree produced by pddlParser#durValue. 475 | def exitDurValue(self, ctx:pddlParser.DurValueContext): 476 | pass 477 | 478 | 479 | # Enter a parse tree produced by pddlParser#daEffect. 480 | def enterDaEffect(self, ctx:pddlParser.DaEffectContext): 481 | pass 482 | 483 | # Exit a parse tree produced by pddlParser#daEffect. 484 | def exitDaEffect(self, ctx:pddlParser.DaEffectContext): 485 | pass 486 | 487 | 488 | # Enter a parse tree produced by pddlParser#timedEffect. 489 | def enterTimedEffect(self, ctx:pddlParser.TimedEffectContext): 490 | pass 491 | 492 | # Exit a parse tree produced by pddlParser#timedEffect. 493 | def exitTimedEffect(self, ctx:pddlParser.TimedEffectContext): 494 | pass 495 | 496 | 497 | # Enter a parse tree produced by pddlParser#fAssignDA. 498 | def enterFAssignDA(self, ctx:pddlParser.FAssignDAContext): 499 | pass 500 | 501 | # Exit a parse tree produced by pddlParser#fAssignDA. 502 | def exitFAssignDA(self, ctx:pddlParser.FAssignDAContext): 503 | pass 504 | 505 | 506 | # Enter a parse tree produced by pddlParser#fExpDA. 507 | def enterFExpDA(self, ctx:pddlParser.FExpDAContext): 508 | pass 509 | 510 | # Exit a parse tree produced by pddlParser#fExpDA. 511 | def exitFExpDA(self, ctx:pddlParser.FExpDAContext): 512 | pass 513 | 514 | 515 | # Enter a parse tree produced by pddlParser#assignOpT. 516 | def enterAssignOpT(self, ctx:pddlParser.AssignOpTContext): 517 | pass 518 | 519 | # Exit a parse tree produced by pddlParser#assignOpT. 520 | def exitAssignOpT(self, ctx:pddlParser.AssignOpTContext): 521 | pass 522 | 523 | 524 | # Enter a parse tree produced by pddlParser#problem. 525 | def enterProblem(self, ctx:pddlParser.ProblemContext): 526 | pass 527 | 528 | # Exit a parse tree produced by pddlParser#problem. 529 | def exitProblem(self, ctx:pddlParser.ProblemContext): 530 | pass 531 | 532 | 533 | # Enter a parse tree produced by pddlParser#problemDecl. 534 | def enterProblemDecl(self, ctx:pddlParser.ProblemDeclContext): 535 | pass 536 | 537 | # Exit a parse tree produced by pddlParser#problemDecl. 538 | def exitProblemDecl(self, ctx:pddlParser.ProblemDeclContext): 539 | pass 540 | 541 | 542 | # Enter a parse tree produced by pddlParser#problemDomain. 543 | def enterProblemDomain(self, ctx:pddlParser.ProblemDomainContext): 544 | pass 545 | 546 | # Exit a parse tree produced by pddlParser#problemDomain. 547 | def exitProblemDomain(self, ctx:pddlParser.ProblemDomainContext): 548 | pass 549 | 550 | 551 | # Enter a parse tree produced by pddlParser#objectDecl. 552 | def enterObjectDecl(self, ctx:pddlParser.ObjectDeclContext): 553 | pass 554 | 555 | # Exit a parse tree produced by pddlParser#objectDecl. 556 | def exitObjectDecl(self, ctx:pddlParser.ObjectDeclContext): 557 | pass 558 | 559 | 560 | # Enter a parse tree produced by pddlParser#init. 561 | def enterInit(self, ctx:pddlParser.InitContext): 562 | pass 563 | 564 | # Exit a parse tree produced by pddlParser#init. 565 | def exitInit(self, ctx:pddlParser.InitContext): 566 | pass 567 | 568 | 569 | # Enter a parse tree produced by pddlParser#initEl. 570 | def enterInitEl(self, ctx:pddlParser.InitElContext): 571 | pass 572 | 573 | # Exit a parse tree produced by pddlParser#initEl. 574 | def exitInitEl(self, ctx:pddlParser.InitElContext): 575 | pass 576 | 577 | 578 | # Enter a parse tree produced by pddlParser#nameLiteral. 579 | def enterNameLiteral(self, ctx:pddlParser.NameLiteralContext): 580 | pass 581 | 582 | # Exit a parse tree produced by pddlParser#nameLiteral. 583 | def exitNameLiteral(self, ctx:pddlParser.NameLiteralContext): 584 | pass 585 | 586 | 587 | # Enter a parse tree produced by pddlParser#atomicNameFormula. 588 | def enterAtomicNameFormula(self, ctx:pddlParser.AtomicNameFormulaContext): 589 | pass 590 | 591 | # Exit a parse tree produced by pddlParser#atomicNameFormula. 592 | def exitAtomicNameFormula(self, ctx:pddlParser.AtomicNameFormulaContext): 593 | pass 594 | 595 | 596 | # Enter a parse tree produced by pddlParser#goal. 597 | def enterGoal(self, ctx:pddlParser.GoalContext): 598 | pass 599 | 600 | # Exit a parse tree produced by pddlParser#goal. 601 | def exitGoal(self, ctx:pddlParser.GoalContext): 602 | pass 603 | 604 | 605 | # Enter a parse tree produced by pddlParser#probConstraints. 606 | def enterProbConstraints(self, ctx:pddlParser.ProbConstraintsContext): 607 | pass 608 | 609 | # Exit a parse tree produced by pddlParser#probConstraints. 610 | def exitProbConstraints(self, ctx:pddlParser.ProbConstraintsContext): 611 | pass 612 | 613 | 614 | # Enter a parse tree produced by pddlParser#prefConGD. 615 | def enterPrefConGD(self, ctx:pddlParser.PrefConGDContext): 616 | pass 617 | 618 | # Exit a parse tree produced by pddlParser#prefConGD. 619 | def exitPrefConGD(self, ctx:pddlParser.PrefConGDContext): 620 | pass 621 | 622 | 623 | # Enter a parse tree produced by pddlParser#metricSpec. 624 | def enterMetricSpec(self, ctx:pddlParser.MetricSpecContext): 625 | pass 626 | 627 | # Exit a parse tree produced by pddlParser#metricSpec. 628 | def exitMetricSpec(self, ctx:pddlParser.MetricSpecContext): 629 | pass 630 | 631 | 632 | # Enter a parse tree produced by pddlParser#optimization. 633 | def enterOptimization(self, ctx:pddlParser.OptimizationContext): 634 | pass 635 | 636 | # Exit a parse tree produced by pddlParser#optimization. 637 | def exitOptimization(self, ctx:pddlParser.OptimizationContext): 638 | pass 639 | 640 | 641 | # Enter a parse tree produced by pddlParser#metricFExp. 642 | def enterMetricFExp(self, ctx:pddlParser.MetricFExpContext): 643 | pass 644 | 645 | # Exit a parse tree produced by pddlParser#metricFExp. 646 | def exitMetricFExp(self, ctx:pddlParser.MetricFExpContext): 647 | pass 648 | 649 | 650 | # Enter a parse tree produced by pddlParser#conGD. 651 | def enterConGD(self, ctx:pddlParser.ConGDContext): 652 | pass 653 | 654 | # Exit a parse tree produced by pddlParser#conGD. 655 | def exitConGD(self, ctx:pddlParser.ConGDContext): 656 | pass 657 | 658 | 659 | # Enter a parse tree produced by pddlParser#name. 660 | def enterName(self, ctx:pddlParser.NameContext): 661 | pass 662 | 663 | # Exit a parse tree produced by pddlParser#name. 664 | def exitName(self, ctx:pddlParser.NameContext): 665 | pass 666 | 667 | 668 | -------------------------------------------------------------------------------- /pddlpy/pddlLexer.py: -------------------------------------------------------------------------------- 1 | # Generated from pddl.g4 by ANTLR 4.7 2 | from antlr4 import * 3 | from io import StringIO 4 | from typing.io import TextIO 5 | import sys 6 | 7 | 8 | def serializedATN(): 9 | with StringIO() as buf: 10 | buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2K") 11 | buf.write("\u03e7\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") 12 | buf.write("\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r") 13 | buf.write("\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23") 14 | buf.write("\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30") 15 | buf.write("\4\31\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36") 16 | buf.write("\t\36\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%") 17 | buf.write("\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4,\t,\4-\t-\4.") 18 | buf.write("\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64") 19 | buf.write("\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:") 20 | buf.write("\4;\t;\4<\t<\4=\t=\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\t") 21 | buf.write("C\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I\tI\4J\tJ\4K\tK\4L\t") 22 | buf.write("L\4M\tM\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\4\3\4\3") 23 | buf.write("\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6") 24 | buf.write("\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3") 25 | buf.write("\7\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n") 26 | buf.write("\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13") 27 | buf.write("\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f") 28 | buf.write("\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16") 29 | buf.write("\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16") 30 | buf.write("\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20") 31 | buf.write("\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\21") 32 | buf.write("\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21") 33 | buf.write("\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\23") 34 | buf.write("\3\23\3\23\3\23\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\26") 35 | buf.write("\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27") 36 | buf.write("\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31") 37 | buf.write("\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31") 38 | buf.write("\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32") 39 | buf.write("\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33") 40 | buf.write("\3\33\3\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34") 41 | buf.write("\3\34\3\34\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\37") 42 | buf.write("\3\37\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3!\3!\3!\3!\3\"") 43 | buf.write("\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3#\3#\3#\3#\3#\3$\3$") 44 | buf.write("\3%\3%\3&\3&\3\'\3\'\3(\3(\3)\3)\3*\3*\3*\3+\3+\3+\3,") 45 | buf.write("\3,\3,\3,\3,\3,\3,\3-\3-\3-\3-\3-\3-\3-\3-\3-\3.\3.\3") 46 | buf.write(".\3.\3.\3.\3.\3.\3.\3.\3.\3/\3/\3/\3/\3/\3/\3/\3/\3/\3") 47 | buf.write("\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\61\3\61") 48 | buf.write("\3\61\3\61\3\61\3\61\3\61\3\61\3\61\3\61\3\62\3\62\3\62") 49 | buf.write("\3\62\3\62\3\62\3\62\3\62\3\63\3\63\3\63\3\63\3\63\3\63") 50 | buf.write("\3\63\3\63\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\64") 51 | buf.write("\3\65\3\65\3\65\3\65\3\65\3\65\3\66\3\66\3\66\3\66\3\66") 52 | buf.write("\3\66\3\67\3\67\3\67\3\67\3\67\3\67\3\67\3\67\38\38\3") 53 | buf.write("8\38\38\38\38\38\38\39\39\39\39\39\39\39\39\39\3:\3:\3") 54 | buf.write(":\3:\3:\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3;\3;\3;\3;\3") 55 | buf.write(";\3;\3;\3<\3<\3<\3<\3<\3<\3<\3=\3=\3=\3=\3=\3=\3=\3=\3") 56 | buf.write("=\3>\3>\3>\3>\3>\3>\3>\3?\3?\3?\3?\3?\3?\3?\3?\3?\3?\3") 57 | buf.write("?\3?\3?\3@\3@\3@\3@\3@\3@\3@\3@\3@\3@\3@\3@\3@\3@\3@\3") 58 | buf.write("A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3B\3B\3") 59 | buf.write("B\3B\3B\3B\3B\3B\3B\3B\3B\3B\3B\3B\3C\3C\3C\3C\3C\3C\3") 60 | buf.write("C\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3E\3") 61 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 62 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 63 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 64 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 65 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 66 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 67 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 68 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 69 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 70 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 71 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 72 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 73 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 74 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3") 75 | buf.write("E\3E\3E\3E\3E\3E\3E\3E\3E\5E\u03ad\nE\3F\3F\7F\u03b1\n") 76 | buf.write("F\fF\16F\u03b4\13F\3G\3G\3H\3H\5H\u03ba\nH\3I\3I\3I\7") 77 | buf.write("I\u03bf\nI\fI\16I\u03c2\13I\3J\6J\u03c5\nJ\rJ\16J\u03c6") 78 | buf.write("\3J\3J\6J\u03cb\nJ\rJ\16J\u03cc\5J\u03cf\nJ\3K\3K\3L\3") 79 | buf.write("L\7L\u03d5\nL\fL\16L\u03d8\13L\3L\5L\u03db\nL\3L\3L\3") 80 | buf.write("L\3L\3M\6M\u03e2\nM\rM\16M\u03e3\3M\3M\2\2N\3\3\5\4\7") 81 | buf.write("\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17") 82 | buf.write("\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63") 83 | buf.write("\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-") 84 | buf.write("Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u{?}") 85 | buf.write("@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008d") 86 | buf.write("\2\u008f\2\u0091H\u0093I\u0095\2\u0097J\u0099K\3\2\6\4") 87 | buf.write("\2C\\c|\5\2//\62;aa\4\2\f\f\17\17\5\2\13\f\17\17\"\"\2") 88 | buf.write("\u03fb\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2") 89 | buf.write("\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2") 90 | buf.write("\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33") 91 | buf.write("\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2") 92 | buf.write("\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2") 93 | buf.write("\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2") 94 | buf.write("\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2") 95 | buf.write("\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3") 96 | buf.write("\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S") 97 | buf.write("\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2") 98 | buf.write("]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2") 99 | buf.write("\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2") 100 | buf.write("\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2") 101 | buf.write("\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2") 102 | buf.write("\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089") 103 | buf.write("\3\2\2\2\2\u008b\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2") 104 | buf.write("\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\3\u009b\3\2\2\2\5\u009d") 105 | buf.write("\3\2\2\2\7\u00a4\3\2\2\2\t\u00a6\3\2\2\2\13\u00ad\3\2") 106 | buf.write("\2\2\r\u00bb\3\2\2\2\17\u00c2\3\2\2\2\21\u00c4\3\2\2\2") 107 | buf.write("\23\u00cb\3\2\2\2\25\u00d6\3\2\2\2\27\u00dd\3\2\2\2\31") 108 | buf.write("\u00e8\3\2\2\2\33\u00f4\3\2\2\2\35\u0101\3\2\2\2\37\u0109") 109 | buf.write("\3\2\2\2!\u0115\3\2\2\2#\u0123\3\2\2\2%\u012b\3\2\2\2") 110 | buf.write("\'\u012f\3\2\2\2)\u0132\3\2\2\2+\u0136\3\2\2\2-\u013c") 111 | buf.write("\3\2\2\2/\u0143\3\2\2\2\61\u014a\3\2\2\2\63\u015b\3\2") 112 | buf.write("\2\2\65\u0165\3\2\2\2\67\u0170\3\2\2\29\u017b\3\2\2\2") 113 | buf.write(";\u017e\3\2\2\2=\u0183\3\2\2\2?\u0189\3\2\2\2A\u018d\3") 114 | buf.write("\2\2\2C\u0191\3\2\2\2E\u019a\3\2\2\2G\u019f\3\2\2\2I\u01a1") 115 | buf.write("\3\2\2\2K\u01a3\3\2\2\2M\u01a5\3\2\2\2O\u01a7\3\2\2\2") 116 | buf.write("Q\u01a9\3\2\2\2S\u01ab\3\2\2\2U\u01ae\3\2\2\2W\u01b1\3") 117 | buf.write("\2\2\2Y\u01b8\3\2\2\2[\u01c1\3\2\2\2]\u01cc\3\2\2\2_\u01d5") 118 | buf.write("\3\2\2\2a\u01de\3\2\2\2c\u01e8\3\2\2\2e\u01f0\3\2\2\2") 119 | buf.write("g\u01f8\3\2\2\2i\u0201\3\2\2\2k\u0207\3\2\2\2m\u020d\3") 120 | buf.write("\2\2\2o\u0215\3\2\2\2q\u021e\3\2\2\2s\u0227\3\2\2\2u\u0232") 121 | buf.write("\3\2\2\2w\u023e\3\2\2\2y\u0245\3\2\2\2{\u024e\3\2\2\2") 122 | buf.write("}\u0255\3\2\2\2\177\u0262\3\2\2\2\u0081\u0271\3\2\2\2") 123 | buf.write("\u0083\u0281\3\2\2\2\u0085\u028f\3\2\2\2\u0087\u029b\3") 124 | buf.write("\2\2\2\u0089\u03ac\3\2\2\2\u008b\u03ae\3\2\2\2\u008d\u03b5") 125 | buf.write("\3\2\2\2\u008f\u03b9\3\2\2\2\u0091\u03bb\3\2\2\2\u0093") 126 | buf.write("\u03c4\3\2\2\2\u0095\u03d0\3\2\2\2\u0097\u03d2\3\2\2\2") 127 | buf.write("\u0099\u03e1\3\2\2\2\u009b\u009c\7*\2\2\u009c\4\3\2\2") 128 | buf.write("\2\u009d\u009e\7f\2\2\u009e\u009f\7g\2\2\u009f\u00a0\7") 129 | buf.write("h\2\2\u00a0\u00a1\7k\2\2\u00a1\u00a2\7p\2\2\u00a2\u00a3") 130 | buf.write("\7g\2\2\u00a3\6\3\2\2\2\u00a4\u00a5\7+\2\2\u00a5\b\3\2") 131 | buf.write("\2\2\u00a6\u00a7\7f\2\2\u00a7\u00a8\7q\2\2\u00a8\u00a9") 132 | buf.write("\7o\2\2\u00a9\u00aa\7c\2\2\u00aa\u00ab\7k\2\2\u00ab\u00ac") 133 | buf.write("\7p\2\2\u00ac\n\3\2\2\2\u00ad\u00ae\7<\2\2\u00ae\u00af") 134 | buf.write("\7t\2\2\u00af\u00b0\7g\2\2\u00b0\u00b1\7s\2\2\u00b1\u00b2") 135 | buf.write("\7w\2\2\u00b2\u00b3\7k\2\2\u00b3\u00b4\7t\2\2\u00b4\u00b5") 136 | buf.write("\7g\2\2\u00b5\u00b6\7o\2\2\u00b6\u00b7\7g\2\2\u00b7\u00b8") 137 | buf.write("\7p\2\2\u00b8\u00b9\7v\2\2\u00b9\u00ba\7u\2\2\u00ba\f") 138 | buf.write("\3\2\2\2\u00bb\u00bc\7<\2\2\u00bc\u00bd\7v\2\2\u00bd\u00be") 139 | buf.write("\7{\2\2\u00be\u00bf\7r\2\2\u00bf\u00c0\7g\2\2\u00c0\u00c1") 140 | buf.write("\7u\2\2\u00c1\16\3\2\2\2\u00c2\u00c3\7/\2\2\u00c3\20\3") 141 | buf.write("\2\2\2\u00c4\u00c5\7g\2\2\u00c5\u00c6\7k\2\2\u00c6\u00c7") 142 | buf.write("\7v\2\2\u00c7\u00c8\7j\2\2\u00c8\u00c9\7g\2\2\u00c9\u00ca") 143 | buf.write("\7t\2\2\u00ca\22\3\2\2\2\u00cb\u00cc\7<\2\2\u00cc\u00cd") 144 | buf.write("\7h\2\2\u00cd\u00ce\7w\2\2\u00ce\u00cf\7p\2\2\u00cf\u00d0") 145 | buf.write("\7e\2\2\u00d0\u00d1\7v\2\2\u00d1\u00d2\7k\2\2\u00d2\u00d3") 146 | buf.write("\7q\2\2\u00d3\u00d4\7p\2\2\u00d4\u00d5\7u\2\2\u00d5\24") 147 | buf.write("\3\2\2\2\u00d6\u00d7\7p\2\2\u00d7\u00d8\7w\2\2\u00d8\u00d9") 148 | buf.write("\7o\2\2\u00d9\u00da\7d\2\2\u00da\u00db\7g\2\2\u00db\u00dc") 149 | buf.write("\7t\2\2\u00dc\26\3\2\2\2\u00dd\u00de\7<\2\2\u00de\u00df") 150 | buf.write("\7e\2\2\u00df\u00e0\7q\2\2\u00e0\u00e1\7p\2\2\u00e1\u00e2") 151 | buf.write("\7u\2\2\u00e2\u00e3\7v\2\2\u00e3\u00e4\7c\2\2\u00e4\u00e5") 152 | buf.write("\7p\2\2\u00e5\u00e6\7v\2\2\u00e6\u00e7\7u\2\2\u00e7\30") 153 | buf.write("\3\2\2\2\u00e8\u00e9\7<\2\2\u00e9\u00ea\7r\2\2\u00ea\u00eb") 154 | buf.write("\7t\2\2\u00eb\u00ec\7g\2\2\u00ec\u00ed\7f\2\2\u00ed\u00ee") 155 | buf.write("\7k\2\2\u00ee\u00ef\7e\2\2\u00ef\u00f0\7c\2\2\u00f0\u00f1") 156 | buf.write("\7v\2\2\u00f1\u00f2\7g\2\2\u00f2\u00f3\7u\2\2\u00f3\32") 157 | buf.write("\3\2\2\2\u00f4\u00f5\7<\2\2\u00f5\u00f6\7e\2\2\u00f6\u00f7") 158 | buf.write("\7q\2\2\u00f7\u00f8\7p\2\2\u00f8\u00f9\7u\2\2\u00f9\u00fa") 159 | buf.write("\7v\2\2\u00fa\u00fb\7t\2\2\u00fb\u00fc\7c\2\2\u00fc\u00fd") 160 | buf.write("\7k\2\2\u00fd\u00fe\7p\2\2\u00fe\u00ff\7v\2\2\u00ff\u0100") 161 | buf.write("\7u\2\2\u0100\34\3\2\2\2\u0101\u0102\7<\2\2\u0102\u0103") 162 | buf.write("\7c\2\2\u0103\u0104\7e\2\2\u0104\u0105\7v\2\2\u0105\u0106") 163 | buf.write("\7k\2\2\u0106\u0107\7q\2\2\u0107\u0108\7p\2\2\u0108\36") 164 | buf.write("\3\2\2\2\u0109\u010a\7<\2\2\u010a\u010b\7r\2\2\u010b\u010c") 165 | buf.write("\7c\2\2\u010c\u010d\7t\2\2\u010d\u010e\7c\2\2\u010e\u010f") 166 | buf.write("\7o\2\2\u010f\u0110\7g\2\2\u0110\u0111\7v\2\2\u0111\u0112") 167 | buf.write("\7g\2\2\u0112\u0113\7t\2\2\u0113\u0114\7u\2\2\u0114 \3") 168 | buf.write("\2\2\2\u0115\u0116\7<\2\2\u0116\u0117\7r\2\2\u0117\u0118") 169 | buf.write("\7t\2\2\u0118\u0119\7g\2\2\u0119\u011a\7e\2\2\u011a\u011b") 170 | buf.write("\7q\2\2\u011b\u011c\7p\2\2\u011c\u011d\7f\2\2\u011d\u011e") 171 | buf.write("\7k\2\2\u011e\u011f\7v\2\2\u011f\u0120\7k\2\2\u0120\u0121") 172 | buf.write("\7q\2\2\u0121\u0122\7p\2\2\u0122\"\3\2\2\2\u0123\u0124") 173 | buf.write("\7<\2\2\u0124\u0125\7g\2\2\u0125\u0126\7h\2\2\u0126\u0127") 174 | buf.write("\7h\2\2\u0127\u0128\7g\2\2\u0128\u0129\7e\2\2\u0129\u012a") 175 | buf.write("\7v\2\2\u012a$\3\2\2\2\u012b\u012c\7c\2\2\u012c\u012d") 176 | buf.write("\7p\2\2\u012d\u012e\7f\2\2\u012e&\3\2\2\2\u012f\u0130") 177 | buf.write("\7q\2\2\u0130\u0131\7t\2\2\u0131(\3\2\2\2\u0132\u0133") 178 | buf.write("\7p\2\2\u0133\u0134\7q\2\2\u0134\u0135\7v\2\2\u0135*\3") 179 | buf.write("\2\2\2\u0136\u0137\7k\2\2\u0137\u0138\7o\2\2\u0138\u0139") 180 | buf.write("\7r\2\2\u0139\u013a\7n\2\2\u013a\u013b\7{\2\2\u013b,\3") 181 | buf.write("\2\2\2\u013c\u013d\7g\2\2\u013d\u013e\7z\2\2\u013e\u013f") 182 | buf.write("\7k\2\2\u013f\u0140\7u\2\2\u0140\u0141\7v\2\2\u0141\u0142") 183 | buf.write("\7u\2\2\u0142.\3\2\2\2\u0143\u0144\7h\2\2\u0144\u0145") 184 | buf.write("\7q\2\2\u0145\u0146\7t\2\2\u0146\u0147\7c\2\2\u0147\u0148") 185 | buf.write("\7n\2\2\u0148\u0149\7n\2\2\u0149\60\3\2\2\2\u014a\u014b") 186 | buf.write("\7<\2\2\u014b\u014c\7f\2\2\u014c\u014d\7w\2\2\u014d\u014e") 187 | buf.write("\7t\2\2\u014e\u014f\7c\2\2\u014f\u0150\7v\2\2\u0150\u0151") 188 | buf.write("\7k\2\2\u0151\u0152\7x\2\2\u0152\u0153\7g\2\2\u0153\u0154") 189 | buf.write("\7/\2\2\u0154\u0155\7c\2\2\u0155\u0156\7e\2\2\u0156\u0157") 190 | buf.write("\7v\2\2\u0157\u0158\7k\2\2\u0158\u0159\7q\2\2\u0159\u015a") 191 | buf.write("\7p\2\2\u015a\62\3\2\2\2\u015b\u015c\7<\2\2\u015c\u015d") 192 | buf.write("\7f\2\2\u015d\u015e\7w\2\2\u015e\u015f\7t\2\2\u015f\u0160") 193 | buf.write("\7c\2\2\u0160\u0161\7v\2\2\u0161\u0162\7k\2\2\u0162\u0163") 194 | buf.write("\7q\2\2\u0163\u0164\7p\2\2\u0164\64\3\2\2\2\u0165\u0166") 195 | buf.write("\7<\2\2\u0166\u0167\7e\2\2\u0167\u0168\7q\2\2\u0168\u0169") 196 | buf.write("\7p\2\2\u0169\u016a\7f\2\2\u016a\u016b\7k\2\2\u016b\u016c") 197 | buf.write("\7v\2\2\u016c\u016d\7k\2\2\u016d\u016e\7q\2\2\u016e\u016f") 198 | buf.write("\7p\2\2\u016f\66\3\2\2\2\u0170\u0171\7r\2\2\u0171\u0172") 199 | buf.write("\7t\2\2\u0172\u0173\7g\2\2\u0173\u0174\7h\2\2\u0174\u0175") 200 | buf.write("\7g\2\2\u0175\u0176\7t\2\2\u0176\u0177\7g\2\2\u0177\u0178") 201 | buf.write("\7p\2\2\u0178\u0179\7e\2\2\u0179\u017a\7g\2\2\u017a8\3") 202 | buf.write("\2\2\2\u017b\u017c\7c\2\2\u017c\u017d\7v\2\2\u017d:\3") 203 | buf.write("\2\2\2\u017e\u017f\7q\2\2\u017f\u0180\7x\2\2\u0180\u0181") 204 | buf.write("\7g\2\2\u0181\u0182\7t\2\2\u0182<\3\2\2\2\u0183\u0184") 205 | buf.write("\7u\2\2\u0184\u0185\7v\2\2\u0185\u0186\7c\2\2\u0186\u0187") 206 | buf.write("\7t\2\2\u0187\u0188\7v\2\2\u0188>\3\2\2\2\u0189\u018a") 207 | buf.write("\7g\2\2\u018a\u018b\7p\2\2\u018b\u018c\7f\2\2\u018c@\3") 208 | buf.write("\2\2\2\u018d\u018e\7c\2\2\u018e\u018f\7n\2\2\u018f\u0190") 209 | buf.write("\7n\2\2\u0190B\3\2\2\2\u0191\u0192\7<\2\2\u0192\u0193") 210 | buf.write("\7f\2\2\u0193\u0194\7g\2\2\u0194\u0195\7t\2\2\u0195\u0196") 211 | buf.write("\7k\2\2\u0196\u0197\7x\2\2\u0197\u0198\7g\2\2\u0198\u0199") 212 | buf.write("\7f\2\2\u0199D\3\2\2\2\u019a\u019b\7y\2\2\u019b\u019c") 213 | buf.write("\7j\2\2\u019c\u019d\7g\2\2\u019d\u019e\7p\2\2\u019eF\3") 214 | buf.write("\2\2\2\u019f\u01a0\7,\2\2\u01a0H\3\2\2\2\u01a1\u01a2\7") 215 | buf.write("-\2\2\u01a2J\3\2\2\2\u01a3\u01a4\7\61\2\2\u01a4L\3\2\2") 216 | buf.write("\2\u01a5\u01a6\7@\2\2\u01a6N\3\2\2\2\u01a7\u01a8\7>\2") 217 | buf.write("\2\u01a8P\3\2\2\2\u01a9\u01aa\7?\2\2\u01aaR\3\2\2\2\u01ab") 218 | buf.write("\u01ac\7@\2\2\u01ac\u01ad\7?\2\2\u01adT\3\2\2\2\u01ae") 219 | buf.write("\u01af\7>\2\2\u01af\u01b0\7?\2\2\u01b0V\3\2\2\2\u01b1") 220 | buf.write("\u01b2\7c\2\2\u01b2\u01b3\7u\2\2\u01b3\u01b4\7u\2\2\u01b4") 221 | buf.write("\u01b5\7k\2\2\u01b5\u01b6\7i\2\2\u01b6\u01b7\7p\2\2\u01b7") 222 | buf.write("X\3\2\2\2\u01b8\u01b9\7u\2\2\u01b9\u01ba\7e\2\2\u01ba") 223 | buf.write("\u01bb\7c\2\2\u01bb\u01bc\7n\2\2\u01bc\u01bd\7g\2\2\u01bd") 224 | buf.write("\u01be\7/\2\2\u01be\u01bf\7w\2\2\u01bf\u01c0\7r\2\2\u01c0") 225 | buf.write("Z\3\2\2\2\u01c1\u01c2\7u\2\2\u01c2\u01c3\7e\2\2\u01c3") 226 | buf.write("\u01c4\7c\2\2\u01c4\u01c5\7n\2\2\u01c5\u01c6\7g\2\2\u01c6") 227 | buf.write("\u01c7\7/\2\2\u01c7\u01c8\7f\2\2\u01c8\u01c9\7q\2\2\u01c9") 228 | buf.write("\u01ca\7y\2\2\u01ca\u01cb\7p\2\2\u01cb\\\3\2\2\2\u01cc") 229 | buf.write("\u01cd\7k\2\2\u01cd\u01ce\7p\2\2\u01ce\u01cf\7e\2\2\u01cf") 230 | buf.write("\u01d0\7t\2\2\u01d0\u01d1\7g\2\2\u01d1\u01d2\7c\2\2\u01d2") 231 | buf.write("\u01d3\7u\2\2\u01d3\u01d4\7g\2\2\u01d4^\3\2\2\2\u01d5") 232 | buf.write("\u01d6\7f\2\2\u01d6\u01d7\7g\2\2\u01d7\u01d8\7e\2\2\u01d8") 233 | buf.write("\u01d9\7t\2\2\u01d9\u01da\7g\2\2\u01da\u01db\7c\2\2\u01db") 234 | buf.write("\u01dc\7u\2\2\u01dc\u01dd\7g\2\2\u01dd`\3\2\2\2\u01de") 235 | buf.write("\u01df\7A\2\2\u01df\u01e0\7f\2\2\u01e0\u01e1\7w\2\2\u01e1") 236 | buf.write("\u01e2\7t\2\2\u01e2\u01e3\7c\2\2\u01e3\u01e4\7v\2\2\u01e4") 237 | buf.write("\u01e5\7k\2\2\u01e5\u01e6\7q\2\2\u01e6\u01e7\7p\2\2\u01e7") 238 | buf.write("b\3\2\2\2\u01e8\u01e9\7r\2\2\u01e9\u01ea\7t\2\2\u01ea") 239 | buf.write("\u01eb\7q\2\2\u01eb\u01ec\7d\2\2\u01ec\u01ed\7n\2\2\u01ed") 240 | buf.write("\u01ee\7g\2\2\u01ee\u01ef\7o\2\2\u01efd\3\2\2\2\u01f0") 241 | buf.write("\u01f1\7<\2\2\u01f1\u01f2\7f\2\2\u01f2\u01f3\7q\2\2\u01f3") 242 | buf.write("\u01f4\7o\2\2\u01f4\u01f5\7c\2\2\u01f5\u01f6\7k\2\2\u01f6") 243 | buf.write("\u01f7\7p\2\2\u01f7f\3\2\2\2\u01f8\u01f9\7<\2\2\u01f9") 244 | buf.write("\u01fa\7q\2\2\u01fa\u01fb\7d\2\2\u01fb\u01fc\7l\2\2\u01fc") 245 | buf.write("\u01fd\7g\2\2\u01fd\u01fe\7e\2\2\u01fe\u01ff\7v\2\2\u01ff") 246 | buf.write("\u0200\7u\2\2\u0200h\3\2\2\2\u0201\u0202\7<\2\2\u0202") 247 | buf.write("\u0203\7k\2\2\u0203\u0204\7p\2\2\u0204\u0205\7k\2\2\u0205") 248 | buf.write("\u0206\7v\2\2\u0206j\3\2\2\2\u0207\u0208\7<\2\2\u0208") 249 | buf.write("\u0209\7i\2\2\u0209\u020a\7q\2\2\u020a\u020b\7c\2\2\u020b") 250 | buf.write("\u020c\7n\2\2\u020cl\3\2\2\2\u020d\u020e\7<\2\2\u020e") 251 | buf.write("\u020f\7o\2\2\u020f\u0210\7g\2\2\u0210\u0211\7v\2\2\u0211") 252 | buf.write("\u0212\7t\2\2\u0212\u0213\7k\2\2\u0213\u0214\7e\2\2\u0214") 253 | buf.write("n\3\2\2\2\u0215\u0216\7o\2\2\u0216\u0217\7k\2\2\u0217") 254 | buf.write("\u0218\7p\2\2\u0218\u0219\7k\2\2\u0219\u021a\7o\2\2\u021a") 255 | buf.write("\u021b\7k\2\2\u021b\u021c\7|\2\2\u021c\u021d\7g\2\2\u021d") 256 | buf.write("p\3\2\2\2\u021e\u021f\7o\2\2\u021f\u0220\7c\2\2\u0220") 257 | buf.write("\u0221\7z\2\2\u0221\u0222\7k\2\2\u0222\u0223\7o\2\2\u0223") 258 | buf.write("\u0224\7k\2\2\u0224\u0225\7|\2\2\u0225\u0226\7g\2\2\u0226") 259 | buf.write("r\3\2\2\2\u0227\u0228\7v\2\2\u0228\u0229\7q\2\2\u0229") 260 | buf.write("\u022a\7v\2\2\u022a\u022b\7c\2\2\u022b\u022c\7n\2\2\u022c") 261 | buf.write("\u022d\7/\2\2\u022d\u022e\7v\2\2\u022e\u022f\7k\2\2\u022f") 262 | buf.write("\u0230\7o\2\2\u0230\u0231\7g\2\2\u0231t\3\2\2\2\u0232") 263 | buf.write("\u0233\7k\2\2\u0233\u0234\7u\2\2\u0234\u0235\7/\2\2\u0235") 264 | buf.write("\u0236\7x\2\2\u0236\u0237\7k\2\2\u0237\u0238\7q\2\2\u0238") 265 | buf.write("\u0239\7n\2\2\u0239\u023a\7c\2\2\u023a\u023b\7v\2\2\u023b") 266 | buf.write("\u023c\7g\2\2\u023c\u023d\7f\2\2\u023dv\3\2\2\2\u023e") 267 | buf.write("\u023f\7c\2\2\u023f\u0240\7n\2\2\u0240\u0241\7y\2\2\u0241") 268 | buf.write("\u0242\7c\2\2\u0242\u0243\7{\2\2\u0243\u0244\7u\2\2\u0244") 269 | buf.write("x\3\2\2\2\u0245\u0246\7u\2\2\u0246\u0247\7q\2\2\u0247") 270 | buf.write("\u0248\7o\2\2\u0248\u0249\7g\2\2\u0249\u024a\7v\2\2\u024a") 271 | buf.write("\u024b\7k\2\2\u024b\u024c\7o\2\2\u024c\u024d\7g\2\2\u024d") 272 | buf.write("z\3\2\2\2\u024e\u024f\7y\2\2\u024f\u0250\7k\2\2\u0250") 273 | buf.write("\u0251\7v\2\2\u0251\u0252\7j\2\2\u0252\u0253\7k\2\2\u0253") 274 | buf.write("\u0254\7p\2\2\u0254|\3\2\2\2\u0255\u0256\7c\2\2\u0256") 275 | buf.write("\u0257\7v\2\2\u0257\u0258\7/\2\2\u0258\u0259\7o\2\2\u0259") 276 | buf.write("\u025a\7q\2\2\u025a\u025b\7u\2\2\u025b\u025c\7v\2\2\u025c") 277 | buf.write("\u025d\7/\2\2\u025d\u025e\7q\2\2\u025e\u025f\7p\2\2\u025f") 278 | buf.write("\u0260\7e\2\2\u0260\u0261\7g\2\2\u0261~\3\2\2\2\u0262") 279 | buf.write("\u0263\7u\2\2\u0263\u0264\7q\2\2\u0264\u0265\7o\2\2\u0265") 280 | buf.write("\u0266\7g\2\2\u0266\u0267\7v\2\2\u0267\u0268\7k\2\2\u0268") 281 | buf.write("\u0269\7o\2\2\u0269\u026a\7g\2\2\u026a\u026b\7/\2\2\u026b") 282 | buf.write("\u026c\7c\2\2\u026c\u026d\7h\2\2\u026d\u026e\7v\2\2\u026e") 283 | buf.write("\u026f\7g\2\2\u026f\u0270\7t\2\2\u0270\u0080\3\2\2\2\u0271") 284 | buf.write("\u0272\7u\2\2\u0272\u0273\7q\2\2\u0273\u0274\7o\2\2\u0274") 285 | buf.write("\u0275\7g\2\2\u0275\u0276\7v\2\2\u0276\u0277\7k\2\2\u0277") 286 | buf.write("\u0278\7o\2\2\u0278\u0279\7g\2\2\u0279\u027a\7/\2\2\u027a") 287 | buf.write("\u027b\7d\2\2\u027b\u027c\7g\2\2\u027c\u027d\7h\2\2\u027d") 288 | buf.write("\u027e\7q\2\2\u027e\u027f\7t\2\2\u027f\u0280\7g\2\2\u0280") 289 | buf.write("\u0082\3\2\2\2\u0281\u0282\7c\2\2\u0282\u0283\7n\2\2\u0283") 290 | buf.write("\u0284\7y\2\2\u0284\u0285\7c\2\2\u0285\u0286\7{\2\2\u0286") 291 | buf.write("\u0287\7u\2\2\u0287\u0288\7/\2\2\u0288\u0289\7y\2\2\u0289") 292 | buf.write("\u028a\7k\2\2\u028a\u028b\7v\2\2\u028b\u028c\7j\2\2\u028c") 293 | buf.write("\u028d\7k\2\2\u028d\u028e\7p\2\2\u028e\u0084\3\2\2\2\u028f") 294 | buf.write("\u0290\7j\2\2\u0290\u0291\7q\2\2\u0291\u0292\7n\2\2\u0292") 295 | buf.write("\u0293\7f\2\2\u0293\u0294\7/\2\2\u0294\u0295\7f\2\2\u0295") 296 | buf.write("\u0296\7w\2\2\u0296\u0297\7t\2\2\u0297\u0298\7k\2\2\u0298") 297 | buf.write("\u0299\7p\2\2\u0299\u029a\7i\2\2\u029a\u0086\3\2\2\2\u029b") 298 | buf.write("\u029c\7j\2\2\u029c\u029d\7q\2\2\u029d\u029e\7n\2\2\u029e") 299 | buf.write("\u029f\7f\2\2\u029f\u02a0\7/\2\2\u02a0\u02a1\7c\2\2\u02a1") 300 | buf.write("\u02a2\7h\2\2\u02a2\u02a3\7v\2\2\u02a3\u02a4\7g\2\2\u02a4") 301 | buf.write("\u02a5\7t\2\2\u02a5\u0088\3\2\2\2\u02a6\u02a7\7<\2\2\u02a7") 302 | buf.write("\u02a8\7u\2\2\u02a8\u02a9\7v\2\2\u02a9\u02aa\7t\2\2\u02aa") 303 | buf.write("\u02ab\7k\2\2\u02ab\u02ac\7r\2\2\u02ac\u03ad\7u\2\2\u02ad") 304 | buf.write("\u02ae\7<\2\2\u02ae\u02af\7v\2\2\u02af\u02b0\7{\2\2\u02b0") 305 | buf.write("\u02b1\7r\2\2\u02b1\u02b2\7k\2\2\u02b2\u02b3\7p\2\2\u02b3") 306 | buf.write("\u03ad\7i\2\2\u02b4\u02b5\7<\2\2\u02b5\u02b6\7p\2\2\u02b6") 307 | buf.write("\u02b7\7g\2\2\u02b7\u02b8\7i\2\2\u02b8\u02b9\7c\2\2\u02b9") 308 | buf.write("\u02ba\7v\2\2\u02ba\u02bb\7k\2\2\u02bb\u02bc\7x\2\2\u02bc") 309 | buf.write("\u02bd\7g\2\2\u02bd\u02be\7/\2\2\u02be\u02bf\7r\2\2\u02bf") 310 | buf.write("\u02c0\7t\2\2\u02c0\u02c1\7g\2\2\u02c1\u02c2\7e\2\2\u02c2") 311 | buf.write("\u02c3\7q\2\2\u02c3\u02c4\7p\2\2\u02c4\u02c5\7f\2\2\u02c5") 312 | buf.write("\u02c6\7k\2\2\u02c6\u02c7\7v\2\2\u02c7\u02c8\7k\2\2\u02c8") 313 | buf.write("\u02c9\7q\2\2\u02c9\u02ca\7p\2\2\u02ca\u03ad\7u\2\2\u02cb") 314 | buf.write("\u02cc\7<\2\2\u02cc\u02cd\7f\2\2\u02cd\u02ce\7k\2\2\u02ce") 315 | buf.write("\u02cf\7u\2\2\u02cf\u02d0\7l\2\2\u02d0\u02d1\7w\2\2\u02d1") 316 | buf.write("\u02d2\7p\2\2\u02d2\u02d3\7e\2\2\u02d3\u02d4\7v\2\2\u02d4") 317 | buf.write("\u02d5\7k\2\2\u02d5\u02d6\7x\2\2\u02d6\u02d7\7g\2\2\u02d7") 318 | buf.write("\u02d8\7/\2\2\u02d8\u02d9\7r\2\2\u02d9\u02da\7t\2\2\u02da") 319 | buf.write("\u02db\7g\2\2\u02db\u02dc\7e\2\2\u02dc\u02dd\7q\2\2\u02dd") 320 | buf.write("\u02de\7p\2\2\u02de\u02df\7f\2\2\u02df\u02e0\7k\2\2\u02e0") 321 | buf.write("\u02e1\7v\2\2\u02e1\u02e2\7k\2\2\u02e2\u02e3\7q\2\2\u02e3") 322 | buf.write("\u02e4\7p\2\2\u02e4\u03ad\7u\2\2\u02e5\u02e6\7<\2\2\u02e6") 323 | buf.write("\u02e7\7g\2\2\u02e7\u02e8\7s\2\2\u02e8\u02e9\7w\2\2\u02e9") 324 | buf.write("\u02ea\7c\2\2\u02ea\u02eb\7n\2\2\u02eb\u02ec\7k\2\2\u02ec") 325 | buf.write("\u02ed\7v\2\2\u02ed\u03ad\7{\2\2\u02ee\u02ef\7<\2\2\u02ef") 326 | buf.write("\u02f0\7g\2\2\u02f0\u02f1\7z\2\2\u02f1\u02f2\7k\2\2\u02f2") 327 | buf.write("\u02f3\7u\2\2\u02f3\u02f4\7v\2\2\u02f4\u02f5\7g\2\2\u02f5") 328 | buf.write("\u02f6\7p\2\2\u02f6\u02f7\7v\2\2\u02f7\u02f8\7k\2\2\u02f8") 329 | buf.write("\u02f9\7c\2\2\u02f9\u02fa\7n\2\2\u02fa\u02fb\7/\2\2\u02fb") 330 | buf.write("\u02fc\7r\2\2\u02fc\u02fd\7t\2\2\u02fd\u02fe\7g\2\2\u02fe") 331 | buf.write("\u02ff\7e\2\2\u02ff\u0300\7q\2\2\u0300\u0301\7p\2\2\u0301") 332 | buf.write("\u0302\7f\2\2\u0302\u0303\7k\2\2\u0303\u0304\7v\2\2\u0304") 333 | buf.write("\u0305\7k\2\2\u0305\u0306\7q\2\2\u0306\u0307\7p\2\2\u0307") 334 | buf.write("\u03ad\7u\2\2\u0308\u0309\7<\2\2\u0309\u030a\7w\2\2\u030a") 335 | buf.write("\u030b\7p\2\2\u030b\u030c\7k\2\2\u030c\u030d\7x\2\2\u030d") 336 | buf.write("\u030e\7g\2\2\u030e\u030f\7t\2\2\u030f\u0310\7u\2\2\u0310") 337 | buf.write("\u0311\7c\2\2\u0311\u0312\7n\2\2\u0312\u0313\7/\2\2\u0313") 338 | buf.write("\u0314\7r\2\2\u0314\u0315\7t\2\2\u0315\u0316\7g\2\2\u0316") 339 | buf.write("\u0317\7e\2\2\u0317\u0318\7q\2\2\u0318\u0319\7p\2\2\u0319") 340 | buf.write("\u031a\7f\2\2\u031a\u031b\7k\2\2\u031b\u031c\7v\2\2\u031c") 341 | buf.write("\u031d\7k\2\2\u031d\u031e\7q\2\2\u031e\u031f\7p\2\2\u031f") 342 | buf.write("\u03ad\7u\2\2\u0320\u0321\7<\2\2\u0321\u0322\7s\2\2\u0322") 343 | buf.write("\u0323\7w\2\2\u0323\u0324\7c\2\2\u0324\u0325\7p\2\2\u0325") 344 | buf.write("\u0326\7v\2\2\u0326\u0327\7k\2\2\u0327\u0328\7h\2\2\u0328") 345 | buf.write("\u0329\7k\2\2\u0329\u032a\7g\2\2\u032a\u032b\7f\2\2\u032b") 346 | buf.write("\u032c\7/\2\2\u032c\u032d\7r\2\2\u032d\u032e\7t\2\2\u032e") 347 | buf.write("\u032f\7g\2\2\u032f\u0330\7e\2\2\u0330\u0331\7q\2\2\u0331") 348 | buf.write("\u0332\7p\2\2\u0332\u0333\7f\2\2\u0333\u0334\7k\2\2\u0334") 349 | buf.write("\u0335\7v\2\2\u0335\u0336\7k\2\2\u0336\u0337\7q\2\2\u0337") 350 | buf.write("\u0338\7p\2\2\u0338\u03ad\7u\2\2\u0339\u033a\7<\2\2\u033a") 351 | buf.write("\u033b\7e\2\2\u033b\u033c\7q\2\2\u033c\u033d\7p\2\2\u033d") 352 | buf.write("\u033e\7f\2\2\u033e\u033f\7k\2\2\u033f\u0340\7v\2\2\u0340") 353 | buf.write("\u0341\7k\2\2\u0341\u0342\7q\2\2\u0342\u0343\7p\2\2\u0343") 354 | buf.write("\u0344\7c\2\2\u0344\u0345\7n\2\2\u0345\u0346\7/\2\2\u0346") 355 | buf.write("\u0347\7g\2\2\u0347\u0348\7h\2\2\u0348\u0349\7h\2\2\u0349") 356 | buf.write("\u034a\7g\2\2\u034a\u034b\7e\2\2\u034b\u034c\7v\2\2\u034c") 357 | buf.write("\u03ad\7u\2\2\u034d\u034e\7<\2\2\u034e\u034f\7h\2\2\u034f") 358 | buf.write("\u0350\7n\2\2\u0350\u0351\7w\2\2\u0351\u0352\7g\2\2\u0352") 359 | buf.write("\u0353\7p\2\2\u0353\u0354\7v\2\2\u0354\u03ad\7u\2\2\u0355") 360 | buf.write("\u0356\7<\2\2\u0356\u0357\7c\2\2\u0357\u0358\7f\2\2\u0358") 361 | buf.write("\u03ad\7n\2\2\u0359\u035a\7<\2\2\u035a\u035b\7f\2\2\u035b") 362 | buf.write("\u035c\7w\2\2\u035c\u035d\7t\2\2\u035d\u035e\7c\2\2\u035e") 363 | buf.write("\u035f\7v\2\2\u035f\u0360\7k\2\2\u0360\u0361\7x\2\2\u0361") 364 | buf.write("\u0362\7g\2\2\u0362\u0363\7/\2\2\u0363\u0364\7c\2\2\u0364") 365 | buf.write("\u0365\7e\2\2\u0365\u0366\7v\2\2\u0366\u0367\7k\2\2\u0367") 366 | buf.write("\u0368\7q\2\2\u0368\u0369\7p\2\2\u0369\u03ad\7u\2\2\u036a") 367 | buf.write("\u036b\7<\2\2\u036b\u036c\7f\2\2\u036c\u036d\7g\2\2\u036d") 368 | buf.write("\u036e\7t\2\2\u036e\u036f\7k\2\2\u036f\u0370\7x\2\2\u0370") 369 | buf.write("\u0371\7g\2\2\u0371\u0372\7f\2\2\u0372\u0373\7/\2\2\u0373") 370 | buf.write("\u0374\7r\2\2\u0374\u0375\7t\2\2\u0375\u0376\7g\2\2\u0376") 371 | buf.write("\u0377\7f\2\2\u0377\u0378\7k\2\2\u0378\u0379\7e\2\2\u0379") 372 | buf.write("\u037a\7c\2\2\u037a\u037b\7v\2\2\u037b\u037c\7g\2\2\u037c") 373 | buf.write("\u03ad\7u\2\2\u037d\u037e\7<\2\2\u037e\u037f\7v\2\2\u037f") 374 | buf.write("\u0380\7k\2\2\u0380\u0381\7o\2\2\u0381\u0382\7g\2\2\u0382") 375 | buf.write("\u0383\7f\2\2\u0383\u0384\7/\2\2\u0384\u0385\7k\2\2\u0385") 376 | buf.write("\u0386\7p\2\2\u0386\u0387\7k\2\2\u0387\u0388\7v\2\2\u0388") 377 | buf.write("\u0389\7k\2\2\u0389\u038a\7c\2\2\u038a\u038b\7n\2\2\u038b") 378 | buf.write("\u038c\7/\2\2\u038c\u038d\7n\2\2\u038d\u038e\7k\2\2\u038e") 379 | buf.write("\u038f\7v\2\2\u038f\u0390\7g\2\2\u0390\u0391\7t\2\2\u0391") 380 | buf.write("\u0392\7c\2\2\u0392\u0393\7n\2\2\u0393\u03ad\7u\2\2\u0394") 381 | buf.write("\u0395\7<\2\2\u0395\u0396\7r\2\2\u0396\u0397\7t\2\2\u0397") 382 | buf.write("\u0398\7g\2\2\u0398\u0399\7h\2\2\u0399\u039a\7g\2\2\u039a") 383 | buf.write("\u039b\7t\2\2\u039b\u039c\7g\2\2\u039c\u039d\7p\2\2\u039d") 384 | buf.write("\u039e\7e\2\2\u039e\u039f\7g\2\2\u039f\u03ad\7u\2\2\u03a0") 385 | buf.write("\u03a1\7<\2\2\u03a1\u03a2\7e\2\2\u03a2\u03a3\7q\2\2\u03a3") 386 | buf.write("\u03a4\7p\2\2\u03a4\u03a5\7u\2\2\u03a5\u03a6\7v\2\2\u03a6") 387 | buf.write("\u03a7\7t\2\2\u03a7\u03a8\7c\2\2\u03a8\u03a9\7k\2\2\u03a9") 388 | buf.write("\u03aa\7p\2\2\u03aa\u03ab\7v\2\2\u03ab\u03ad\7u\2\2\u03ac") 389 | buf.write("\u02a6\3\2\2\2\u03ac\u02ad\3\2\2\2\u03ac\u02b4\3\2\2\2") 390 | buf.write("\u03ac\u02cb\3\2\2\2\u03ac\u02e5\3\2\2\2\u03ac\u02ee\3") 391 | buf.write("\2\2\2\u03ac\u0308\3\2\2\2\u03ac\u0320\3\2\2\2\u03ac\u0339") 392 | buf.write("\3\2\2\2\u03ac\u034d\3\2\2\2\u03ac\u0355\3\2\2\2\u03ac") 393 | buf.write("\u0359\3\2\2\2\u03ac\u036a\3\2\2\2\u03ac\u037d\3\2\2\2") 394 | buf.write("\u03ac\u0394\3\2\2\2\u03ac\u03a0\3\2\2\2\u03ad\u008a\3") 395 | buf.write("\2\2\2\u03ae\u03b2\5\u008dG\2\u03af\u03b1\5\u008fH\2\u03b0") 396 | buf.write("\u03af\3\2\2\2\u03b1\u03b4\3\2\2\2\u03b2\u03b0\3\2\2\2") 397 | buf.write("\u03b2\u03b3\3\2\2\2\u03b3\u008c\3\2\2\2\u03b4\u03b2\3") 398 | buf.write("\2\2\2\u03b5\u03b6\t\2\2\2\u03b6\u008e\3\2\2\2\u03b7\u03ba") 399 | buf.write("\5\u008dG\2\u03b8\u03ba\t\3\2\2\u03b9\u03b7\3\2\2\2\u03b9") 400 | buf.write("\u03b8\3\2\2\2\u03ba\u0090\3\2\2\2\u03bb\u03bc\7A\2\2") 401 | buf.write("\u03bc\u03c0\5\u008dG\2\u03bd\u03bf\5\u008fH\2\u03be\u03bd") 402 | buf.write("\3\2\2\2\u03bf\u03c2\3\2\2\2\u03c0\u03be\3\2\2\2\u03c0") 403 | buf.write("\u03c1\3\2\2\2\u03c1\u0092\3\2\2\2\u03c2\u03c0\3\2\2\2") 404 | buf.write("\u03c3\u03c5\5\u0095K\2\u03c4\u03c3\3\2\2\2\u03c5\u03c6") 405 | buf.write("\3\2\2\2\u03c6\u03c4\3\2\2\2\u03c6\u03c7\3\2\2\2\u03c7") 406 | buf.write("\u03ce\3\2\2\2\u03c8\u03ca\7\60\2\2\u03c9\u03cb\5\u0095") 407 | buf.write("K\2\u03ca\u03c9\3\2\2\2\u03cb\u03cc\3\2\2\2\u03cc\u03ca") 408 | buf.write("\3\2\2\2\u03cc\u03cd\3\2\2\2\u03cd\u03cf\3\2\2\2\u03ce") 409 | buf.write("\u03c8\3\2\2\2\u03ce\u03cf\3\2\2\2\u03cf\u0094\3\2\2\2") 410 | buf.write("\u03d0\u03d1\4\62;\2\u03d1\u0096\3\2\2\2\u03d2\u03d6\7") 411 | buf.write("=\2\2\u03d3\u03d5\n\4\2\2\u03d4\u03d3\3\2\2\2\u03d5\u03d8") 412 | buf.write("\3\2\2\2\u03d6\u03d4\3\2\2\2\u03d6\u03d7\3\2\2\2\u03d7") 413 | buf.write("\u03da\3\2\2\2\u03d8\u03d6\3\2\2\2\u03d9\u03db\7\17\2") 414 | buf.write("\2\u03da\u03d9\3\2\2\2\u03da\u03db\3\2\2\2\u03db\u03dc") 415 | buf.write("\3\2\2\2\u03dc\u03dd\7\f\2\2\u03dd\u03de\3\2\2\2\u03de") 416 | buf.write("\u03df\bL\2\2\u03df\u0098\3\2\2\2\u03e0\u03e2\t\5\2\2") 417 | buf.write("\u03e1\u03e0\3\2\2\2\u03e2\u03e3\3\2\2\2\u03e3\u03e1\3") 418 | buf.write("\2\2\2\u03e3\u03e4\3\2\2\2\u03e4\u03e5\3\2\2\2\u03e5\u03e6") 419 | buf.write("\bM\2\2\u03e6\u009a\3\2\2\2\r\2\u03ac\u03b2\u03b9\u03c0") 420 | buf.write("\u03c6\u03cc\u03ce\u03d6\u03da\u03e3\3\b\2\2") 421 | return buf.getvalue() 422 | 423 | 424 | class pddlLexer(Lexer): 425 | 426 | atn = ATNDeserializer().deserialize(serializedATN()) 427 | 428 | decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] 429 | 430 | T__0 = 1 431 | T__1 = 2 432 | T__2 = 3 433 | T__3 = 4 434 | T__4 = 5 435 | T__5 = 6 436 | T__6 = 7 437 | T__7 = 8 438 | T__8 = 9 439 | T__9 = 10 440 | T__10 = 11 441 | T__11 = 12 442 | T__12 = 13 443 | T__13 = 14 444 | T__14 = 15 445 | T__15 = 16 446 | T__16 = 17 447 | T__17 = 18 448 | T__18 = 19 449 | T__19 = 20 450 | T__20 = 21 451 | T__21 = 22 452 | T__22 = 23 453 | T__23 = 24 454 | T__24 = 25 455 | T__25 = 26 456 | T__26 = 27 457 | T__27 = 28 458 | T__28 = 29 459 | T__29 = 30 460 | T__30 = 31 461 | T__31 = 32 462 | T__32 = 33 463 | T__33 = 34 464 | T__34 = 35 465 | T__35 = 36 466 | T__36 = 37 467 | T__37 = 38 468 | T__38 = 39 469 | T__39 = 40 470 | T__40 = 41 471 | T__41 = 42 472 | T__42 = 43 473 | T__43 = 44 474 | T__44 = 45 475 | T__45 = 46 476 | T__46 = 47 477 | T__47 = 48 478 | T__48 = 49 479 | T__49 = 50 480 | T__50 = 51 481 | T__51 = 52 482 | T__52 = 53 483 | T__53 = 54 484 | T__54 = 55 485 | T__55 = 56 486 | T__56 = 57 487 | T__57 = 58 488 | T__58 = 59 489 | T__59 = 60 490 | T__60 = 61 491 | T__61 = 62 492 | T__62 = 63 493 | T__63 = 64 494 | T__64 = 65 495 | T__65 = 66 496 | T__66 = 67 497 | REQUIRE_KEY = 68 498 | NAME = 69 499 | VARIABLE = 70 500 | NUMBER = 71 501 | LINE_COMMENT = 72 502 | WHITESPACE = 73 503 | 504 | channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] 505 | 506 | modeNames = [ "DEFAULT_MODE" ] 507 | 508 | literalNames = [ "", 509 | "'('", "'define'", "')'", "'domain'", "':requirements'", "':types'", 510 | "'-'", "'either'", "':functions'", "'number'", "':constants'", 511 | "':predicates'", "':constraints'", "':action'", "':parameters'", 512 | "':precondition'", "':effect'", "'and'", "'or'", "'not'", "'imply'", 513 | "'exists'", "'forall'", "':durative-action'", "':duration'", 514 | "':condition'", "'preference'", "'at'", "'over'", "'start'", 515 | "'end'", "'all'", "':derived'", "'when'", "'*'", "'+'", "'/'", 516 | "'>'", "'<'", "'='", "'>='", "'<='", "'assign'", "'scale-up'", 517 | "'scale-down'", "'increase'", "'decrease'", "'?duration'", "'problem'", 518 | "':domain'", "':objects'", "':init'", "':goal'", "':metric'", 519 | "'minimize'", "'maximize'", "'total-time'", "'is-violated'", 520 | "'always'", "'sometime'", "'within'", "'at-most-once'", "'sometime-after'", 521 | "'sometime-before'", "'always-within'", "'hold-during'", "'hold-after'" ] 522 | 523 | symbolicNames = [ "", 524 | "REQUIRE_KEY", "NAME", "VARIABLE", "NUMBER", "LINE_COMMENT", 525 | "WHITESPACE" ] 526 | 527 | ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", 528 | "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", 529 | "T__14", "T__15", "T__16", "T__17", "T__18", "T__19", 530 | "T__20", "T__21", "T__22", "T__23", "T__24", "T__25", 531 | "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", 532 | "T__32", "T__33", "T__34", "T__35", "T__36", "T__37", 533 | "T__38", "T__39", "T__40", "T__41", "T__42", "T__43", 534 | "T__44", "T__45", "T__46", "T__47", "T__48", "T__49", 535 | "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", 536 | "T__56", "T__57", "T__58", "T__59", "T__60", "T__61", 537 | "T__62", "T__63", "T__64", "T__65", "T__66", "REQUIRE_KEY", 538 | "NAME", "LETTER", "ANY_CHAR", "VARIABLE", "NUMBER", "DIGIT", 539 | "LINE_COMMENT", "WHITESPACE" ] 540 | 541 | grammarFileName = "pddl.g4" 542 | 543 | def __init__(self, input=None, output:TextIO = sys.stdout): 544 | super().__init__(input, output) 545 | self.checkVersion("4.7") 546 | self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) 547 | self._actions = None 548 | self._predicates = None 549 | 550 | 551 | --------------------------------------------------------------------------------