From a94e3c166098b21c9797e6a04ab35a70f9ca3206 Mon Sep 17 00:00:00 2001 From: Erwin Lejeune Date: Sun, 20 Dec 2020 19:13:41 +0100 Subject: [PATCH 1/7] separate build and test --- .github/workflows/pyapp.yml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pyapp.yml b/.github/workflows/pyapp.yml index 16488e4..881dc16 100644 --- a/.github/workflows/pyapp.yml +++ b/.github/workflows/pyapp.yml @@ -4,7 +4,6 @@ on: [push] jobs: build: - runs-on: ubuntu-latest steps: @@ -33,11 +32,17 @@ jobs: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Test with pytest - run: | - pip install pytest - pytest - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 - with: - name: codecov-umbrella + + test: + runs-on: ubuntu-latest + steps: + - name: Test with pytest + run: | + pip install pytest + pytest + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1 + run: | + bash <(curl -s https://codecov.io/bash) + with: + name: codecov-umbrella From e9fcf5887dee3ffbcc0fcc46a74d99719294b3a5 Mon Sep 17 00:00:00 2001 From: Erwin Lejeune Date: Sun, 20 Dec 2020 19:15:02 +0100 Subject: [PATCH 2/7] fix ci yml --- .github/workflows/pyapp.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/pyapp.yml b/.github/workflows/pyapp.yml index 881dc16..8e53034 100644 --- a/.github/workflows/pyapp.yml +++ b/.github/workflows/pyapp.yml @@ -42,7 +42,5 @@ jobs: pytest - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 - run: | - bash <(curl -s https://codecov.io/bash) with: name: codecov-umbrella From da5e082ba948cd95faf564d879716af24d3efd52 Mon Sep 17 00:00:00 2001 From: Erwin Lejeune Date: Sun, 20 Dec 2020 19:17:27 +0100 Subject: [PATCH 3/7] fix ci --- .github/workflows/pyapp.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/workflows/pyapp.yml b/.github/workflows/pyapp.yml index 8e53034..39dc150 100644 --- a/.github/workflows/pyapp.yml +++ b/.github/workflows/pyapp.yml @@ -36,6 +36,31 @@ jobs: test: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v1 + - name: Set up Python 3.7 + uses: actions/setup-python@v1 + with: + python-version: 3.7 + - uses: actions/checkout@v1.0.0 + - uses: julia-actions/setup-julia@v1 + with: + version: '1.4.1' + - name: Install Julia dependencies + run: | + julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/APLA-Toolbox/PDDL.jl"))' + julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/JuliaPy/PyCall.jl"))' + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + python -m pip install julia + python -m pip install pycall + - name: Lint with flake8 + run: | + python -m pip install flake8 + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test with pytest run: | pip install pytest From e9e5e7bfaeaf48153918f95b9d3e45e92aaf508c Mon Sep 17 00:00:00 2001 From: Erwin Lejeune Date: Sun, 20 Dec 2020 19:22:44 +0100 Subject: [PATCH 4/7] separate build and test in ci --- .github/workflows/build.yml | 35 ++++++++++++++++++++++ .github/workflows/{pyapp.yml => tests.yml} | 0 2 files changed, 35 insertions(+) create mode 100644 .github/workflows/build.yml rename .github/workflows/{pyapp.yml => tests.yml} (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..850b1a3 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,35 @@ +name: Python application + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Set up Python 3.7 + uses: actions/setup-python@v1 + with: + python-version: 3.7 + - uses: actions/checkout@v1.0.0 + - uses: julia-actions/setup-julia@v1 + with: + version: '1.4.1' + - name: Install Julia dependencies + run: | + julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/APLA-Toolbox/PDDL.jl"))' + julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/JuliaPy/PyCall.jl"))' + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + python -m pip install julia + python -m pip install pycall + - name: Lint with flake8 + run: | + python -m pip install flake8 + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + diff --git a/.github/workflows/pyapp.yml b/.github/workflows/tests.yml similarity index 100% rename from .github/workflows/pyapp.yml rename to .github/workflows/tests.yml From 00b6898bc2cdc658123ab680040e933e456aad73 Mon Sep 17 00:00:00 2001 From: Erwin Lejeune Date: Sun, 20 Dec 2020 19:23:28 +0100 Subject: [PATCH 5/7] reformat with black --- src/astar.py | 4 ++-- src/automated_planner.py | 5 +++-- src/bfs.py | 20 +++++++++++++++----- src/dfs.py | 4 ++-- src/dijkstra.py | 33 ++++++++++++++++++++++++++------- src/node.py | 15 ++++++++++++--- tests/test_automated_planner.py | 6 ++++-- 7 files changed, 64 insertions(+), 23 deletions(-) diff --git a/src/astar.py b/src/astar.py index 3796a42..74c92f2 100644 --- a/src/astar.py +++ b/src/astar.py @@ -1,7 +1,7 @@ -class AStarBestFirstSearch(): +class AStarBestFirstSearch: def __init__(self, automated_planner): self.automated_planner = automated_planner - + def search(self): print("-/!\- No path found -/!\-") return [] diff --git a/src/automated_planner.py b/src/automated_planner.py index c1aa9a1..cf35914 100644 --- a/src/automated_planner.py +++ b/src/automated_planner.py @@ -16,6 +16,7 @@ from julia import PDDL from time import time as now + class AutomatedPlanner: def __init__(self, domain_path, problem_path): self.pddl = PDDL @@ -28,7 +29,7 @@ def __execute_action(self, action, state): def transition(self, state, action): return self.pddl.transition(self.domain, state, action, check=False) - + def available_actions(self, state): return self.pddl.available(state, self.domain) @@ -66,7 +67,7 @@ def get_state_def_from_path(self, path): trimmed_path = [] for node in path: trimmed_path.append(node.state) - return trimmed_path + return trimmed_path def breadth_first_search(self, time_it=False): if time_it: diff --git a/src/bfs.py b/src/bfs.py index bd8f71c..26c9f96 100644 --- a/src/bfs.py +++ b/src/bfs.py @@ -1,24 +1,34 @@ from .node import Node -class BreadthFirstSearch(): + +class BreadthFirstSearch: def __init__(self, automated_planner): self.visited = [] self.automated_planner = automated_planner self.init = Node(self.automated_planner.initial_state, automated_planner) self.queue = [self.init] - + def search(self): while self.queue: current_node = self.queue.pop(0) if current_node not in self.visited: self.visited.append(current_node) - if self.automated_planner.satisfies(self.automated_planner.problem.goal, current_node.state): + if self.automated_planner.satisfies( + self.automated_planner.problem.goal, current_node.state + ): return current_node - + actions = self.automated_planner.available_actions(current_node.state) for act in actions: - child = Node(state=self.automated_planner.transition(current_node.state, act), automated_planner=self.automated_planner, parent_action=act, parent=current_node) + child = Node( + state=self.automated_planner.transition( + current_node.state, act + ), + automated_planner=self.automated_planner, + parent_action=act, + parent=current_node, + ) if child in self.visited: continue self.queue.append(child) diff --git a/src/dfs.py b/src/dfs.py index fde6f98..60cb086 100644 --- a/src/dfs.py +++ b/src/dfs.py @@ -1,7 +1,7 @@ -class DepthFirstSearch(): +class DepthFirstSearch: def __init__(self, automated_planner): self.automated_planner = automated_planner - + def search(self): print("-/!\- No path found -/!\-") return [] diff --git a/src/dijkstra.py b/src/dijkstra.py index 76ee354..8506600 100644 --- a/src/dijkstra.py +++ b/src/dijkstra.py @@ -2,10 +2,16 @@ import math from .heuristics import zero_heuristic -class DijkstraBestFirstSearch(): + +class DijkstraBestFirstSearch: def __init__(self, automated_planner): self.automated_planner = automated_planner - self.init = Node(self.automated_planner.initial_state, automated_planner, is_closed=False, is_open=True) + self.init = Node( + self.automated_planner.initial_state, + automated_planner, + is_closed=False, + is_open=True, + ) self.open_nodes_n = 1 self.nodes = dict() self.nodes[self.__hash(self.init)] = self.init @@ -17,19 +23,32 @@ def __hash(self, node): def search(self): while self.open_nodes_n > 0: - current_key = min([n for n in self.nodes if self.nodes[n].is_open], key=(lambda k: self.nodes[k].f_cost)) + current_key = min( + [n for n in self.nodes if self.nodes[n].is_open], + key=(lambda k: self.nodes[k].f_cost), + ) current_node = self.nodes[current_key] - if self.automated_planner.satisfies(self.automated_planner.problem.goal, current_node.state): - return current_node + if self.automated_planner.satisfies( + self.automated_planner.problem.goal, current_node.state + ): + return current_node current_node.is_closed = True current_node.is_open = False self.open_nodes_n -= 1 - + actions = self.automated_planner.available_actions(current_node.state) for act in actions: - child = Node(state=self.automated_planner.transition(current_node.state, act), automated_planner=self.automated_planner, parent_action=act, parent=current_node, heuristic=zero_heuristic, is_closed=False, is_open=True) + child = Node( + state=self.automated_planner.transition(current_node.state, act), + automated_planner=self.automated_planner, + parent_action=act, + parent=current_node, + heuristic=zero_heuristic, + is_closed=False, + is_open=True, + ) child_hash = self.__hash(child) if child_hash in self.nodes: if self.nodes[child_hash].is_closed: diff --git a/src/node.py b/src/node.py index c797f14..95c5aba 100644 --- a/src/node.py +++ b/src/node.py @@ -1,5 +1,15 @@ -class Node(): - def __init__(self, state, automated_planner, is_closed=None, is_open=None, parent_action=None, parent=None, g_cost=0, heuristic=None): +class Node: + def __init__( + self, + state, + automated_planner, + is_closed=None, + is_open=None, + parent_action=None, + parent=None, + g_cost=0, + heuristic=None, + ): self.state = state self.parent_action = parent_action self.parent = parent @@ -19,7 +29,6 @@ def __init__(self, state, automated_planner, is_closed=None, is_open=None, paren self.h_cost = 0 self.f_cost = self.g_cost + self.h_cost - self.is_closed = is_closed self.is_open = is_open diff --git a/tests/test_automated_planner.py b/tests/test_automated_planner.py index 7338b63..abb11ab 100644 --- a/tests/test_automated_planner.py +++ b/tests/test_automated_planner.py @@ -18,7 +18,8 @@ def test_available_actions(): apla = AutomatedPlanner("data/domain.pddl", "data/problem.pddl") actions = apla.available_actions(apla.initial_state) - assert(len(actions) > 0) + assert len(actions) > 0 + def test_execute_action(): from src.automated_planner import AutomatedPlanner @@ -26,7 +27,8 @@ def test_execute_action(): apla = AutomatedPlanner("data/domain.pddl", "data/problem.pddl") actions = apla.available_actions(apla.initial_state) new_state = apla.transition(apla.initial_state, actions[0]) - assert(str(new_state) != str(apla.initial_state)) + assert str(new_state) != str(apla.initial_state) + def test_state_assertion(): from src.automated_planner import AutomatedPlanner From 733842f708c7a8b4a128094037afdd347ca8af19 Mon Sep 17 00:00:00 2001 From: Erwin Lejeune Date: Sun, 20 Dec 2020 19:24:28 +0100 Subject: [PATCH 6/7] refactor ci --- .github/workflows/build.yml | 4 ++-- .github/workflows/tests.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 850b1a3..efce7d5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Python application +name: Build on: [push] @@ -32,4 +32,4 @@ jobs: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - + diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 39dc150..09e45c5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,4 +1,4 @@ -name: Python application +name: Run tests on: [push] From 481ae8f9a8f8052ffba01d71621915f6ba47d4f7 Mon Sep 17 00:00:00 2001 From: Erwin Lejeune Date: Sun, 20 Dec 2020 19:28:44 +0100 Subject: [PATCH 7/7] add badges --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 152f90f..e9f4e74 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +![tests](https://github.com/APLA-Toolbox/pyjulia-pddl/workflows/Run%20tests/badge.svg?branch=main&event=push) +![build](https://github.com/APLA-Toolbox/pyjulia-pddl/workflows/Build/badge.svg?branch=main&event=push) + + # Pyjulia PDDL A Python wrapper using JuliaPy for the PDDL.jl package. It implements Planners (Best-First, Breadth-First, Depth-First) as class methods. Easy to use even in REFL mode. The AutomatedPlanner class is clear and understandable, easy to contribute to.