Name | hebg JSON |
Version |
0.2.4
JSON |
| download |
home_page | |
Summary | HEBG: Hierarchial Explainations of Behavior as Graph |
upload_time | 2023-02-04 19:18:23 |
maintainer | |
docs_url | None |
author | Mathïs Fédérico |
requires_python | >=3.7 |
license | GPLv3 license |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
HEBG - Hierachical Explainable Behaviors using Graphs
=====================================================
.. image:: https://badge.fury.io/py/hebg.svg
:alt: [Fury - PyPi stable version]
:target: https://badge.fury.io/py/hebg
.. image:: https://static.pepy.tech/badge/hebg
:alt: [PePy - Downloads]
:target: https://pepy.tech/project/hebg
.. image:: https://static.pepy.tech/badge/hebg/week
:alt: [PePy - Downloads per week]
:target: https://pepy.tech/project/hebg
.. image:: https://app.codacy.com/project/badge/Grade/ec4b296d18f4412398d64a66224c66dd
:alt: [Codacy - Grade]
:target: https://www.codacy.com/gh/IRLL/HEB_graphs/dashboard?utm_source=github.com&utm_medium=referral&utm_content=IRLL/HEB_graphs&utm_campaign=Badge_Grade
.. image:: https://app.codacy.com/project/badge/Coverage/ec4b296d18f4412398d64a66224c66dd
:alt: [Codacy - Coverage]
:target: https://www.codacy.com/gh/IRLL/HEB_graphs/dashboard?utm_source=github.com&utm_medium=referral&utm_content=IRLL/HEB_graphs&utm_campaign=Badge_Coverage
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:alt: [CodeStyle - Black]
:target: https://github.com/psf/black
.. image:: https://img.shields.io/github/license/MathisFederico/Crafting?style=plastic
:alt: [Licence - GPLv3]
:target: https://www.gnu.org/licenses/
This package is meant to build programatic hierarchical behaviors as graphs
to compare them to human explanations of behavior.
We take the definition of "behavior" as a function from observation to action.
Installation
------------
.. code-block:: sh
pip install hebg
Usage
-----
Build a HEBGraph
~~~~~~~~~~~~~~~~
Here is an example to show how could we hierarchicaly build an explanable behavior to pet a cat.
.. code-block:: py3
"""
Here is the hierarchical structure that we would want:
```
PetACat:
IsThereACatAround ?
-> Yes:
PetNearbyCat
-> No:
LookForACat
PetNearbyCat:
IsYourHandNearTheCat ?
-> Yes:
Pet
-> No:
MoveYourHandNearTheCat
```
"""
from hebg import HEBGraph, Action, FeatureCondition, Behavior
from hebg.unrolling import unroll_graph
# Add a fundamental action
class Pet(Action):
def __init__(self) -> None:
super().__init__(action="Pet")
# Add a condition on the observation
class IsYourHandNearTheCat(FeatureCondition):
def __init__(self, hand) -> None:
super().__init__(name="Is hand near the cat ?")
self.hand = hand
def __call__(self, observation):
# Could be a very complex function that returns 1 is the hand is near the cat else 0.
if observation["cat"] == observation[self.hand]:
return int(True) # 1
return int(False) # 0
# Add an unexplainable Behavior (without a graph, but a function that can be called).
class MoveYourHandNearTheCat(Behavior):
def __init__(self) -> None:
super().__init__(name="Move slowly your hand near the cat")
def __call__(self, observation, *args, **kwargs) -> Action:
# Could be a very complex function that returns actions from any given observation
return Action("Move hand to cat")
# Add a sub-behavior
class PetNearbyCat(Behavior):
def __init__(self) -> None:
super().__init__(name="Pet nearby cat")
def build_graph(self) -> HEBGraph:
graph = HEBGraph(self)
is_hand_near_cat = IsYourHandNearTheCat(hand="hand")
graph.add_edge(is_hand_near_cat, MoveYourHandNearTheCat(), index=int(False))
graph.add_edge(is_hand_near_cat, Pet(), index=int(True))
return graph
# Add an other condition on observation
class IsThereACatAround(FeatureCondition):
def __init__(self) -> None:
super().__init__(name="Is there a cat around ?")
def __call__(self, observation):
# Could be a very complex function that returns 1 is there is a cat around else 0.
if "cat" in observation:
return int(True) # 1
return int(False) # 0
# Add an other unexplainable Behavior (without a graph, but a function that can be called).
class LookForACat(Behavior):
def __init__(self) -> None:
super().__init__(name="Look for a nearby cat")
def __call__(self, observation, *args, **kwargs) -> Action:
# Could be a very complex function that returns actions from any given observation
return Action("Move to a cat")
# Finally, add the main Behavior
class PetACat(Behavior):
def __init__(self) -> None:
super().__init__(name="Pet a cat")
def build_graph(self) -> HEBGraph:
graph = HEBGraph(self)
is_a_cat_around = IsThereACatAround()
graph.add_edge(is_a_cat_around, LookForACat(), index=int(False))
graph.add_edge(is_a_cat_around, PetNearbyCat(), index=int(True))
return graph
if __name__ == "__main__":
pet_a_cat_behavior = PetACat()
observation = {
"cat": "sofa",
"hand": "computer",
}
# Call on observation
action = pet_a_cat_behavior(observation)
print(action) # Action("Move hand to cat")
# Obtain networkx graph
graph = pet_a_cat_behavior.graph
print(list(graph.edges(data="index")))
# Draw graph using matplotlib
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
graph.draw(ax)
plt.show()
.. image:: docs/images/PetACatGraph.png
:align: center
Unrolling HEBGraph
~~~~~~~~~~~~~~~~~~
When ploting an HEBGraph of a behavior, only the graph of the behavior itself is shown.
To see the full hierarchical graph (including sub-behaviors), we need to unroll the graph as such:
.. code-block:: py3
from hebg.unrolling import unroll_graph
unrolled_graph = unroll_graph(pet_a_cat_behavior.graph, add_prefix=False)
# Is also a networkx graph
print(list(unrolled_graph.edges(data="index")))
# Draw graph using matplotlib
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
unrolled_graph.draw(ax)
plt.show()
.. image:: docs/images/PetACatGraphUnrolled.png
:align: center
Note that unexplainable behaviors (the one without graphs) are kept as is.
Python code generation from graph
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once you have a HEBGraph, you can use it to generate a working python code that
replicates the HEBGraph's behavior:
.. code-block:: py3
code = pet_a_cat_behavior.graph.generate_source_code()
with open("pet_a_cat.py", "w") as pyfile:
pyfile.write(code)
Will generate the code bellow:
.. code-block:: py3
from hebg.codegen import GeneratedBehavior
# Require 'Look for a nearby cat' behavior to be given.
# Require 'Move slowly your hand near the cat' behavior to be given.
class PetTheCat(GeneratedBehavior):
def __call__(self, observation):
edge_index = self.feature_conditions['Is there a cat around ?'](observation)
if edge_index == 0:
return self.known_behaviors['Look for a nearby cat'](observation)
if edge_index == 1:
edge_index_1 = self.feature_conditions['Is hand near the cat ?'](observation)
if edge_index_1 == 0:
return self.known_behaviors['Move slowly your hand near the cat'](observation)
if edge_index_1 == 1:
return self.actions['Action(Pet)'](observation)
Contributing to HEBG
--------------------
Whenever you encounter a :bug: **bug** or have :tada: **feature request**,
report this via `Github issues <https://github.com/IRLL/HEB_graphs/issues>`_.
If you wish to contribute directly, see `CONTRIBUTING <https://github.com/IRLL/HEB_graphs/blob/main/CONTRIBUTING.rst>`_
Raw data
{
"_id": null,
"home_page": "",
"name": "hebg",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "",
"author": "Math\u00efs F\u00e9d\u00e9rico",
"author_email": "Math\u00efs F\u00e9d\u00e9rico <mathfederico@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/69/1d/dc979fb1d9210cbbac9aacd4e7e7e90880c700823ac0bda9e06f4cc21be0/hebg-0.2.4.tar.gz",
"platform": null,
"description": "HEBG - Hierachical Explainable Behaviors using Graphs\n=====================================================\n\n.. image:: https://badge.fury.io/py/hebg.svg\n :alt: [Fury - PyPi stable version]\n :target: https://badge.fury.io/py/hebg\n\n.. image:: https://static.pepy.tech/badge/hebg\n :alt: [PePy - Downloads]\n :target: https://pepy.tech/project/hebg\n\n.. image:: https://static.pepy.tech/badge/hebg/week\n :alt: [PePy - Downloads per week]\n :target: https://pepy.tech/project/hebg\n\n.. image:: https://app.codacy.com/project/badge/Grade/ec4b296d18f4412398d64a66224c66dd\n :alt: [Codacy - Grade]\n :target: https://www.codacy.com/gh/IRLL/HEB_graphs/dashboard?utm_source=github.com&utm_medium=referral&utm_content=IRLL/HEB_graphs&utm_campaign=Badge_Grade\n\n.. image:: https://app.codacy.com/project/badge/Coverage/ec4b296d18f4412398d64a66224c66dd\n :alt: [Codacy - Coverage]\n :target: https://www.codacy.com/gh/IRLL/HEB_graphs/dashboard?utm_source=github.com&utm_medium=referral&utm_content=IRLL/HEB_graphs&utm_campaign=Badge_Coverage\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :alt: [CodeStyle - Black]\n :target: https://github.com/psf/black\n\n.. image:: https://img.shields.io/github/license/MathisFederico/Crafting?style=plastic\n :alt: [Licence - GPLv3]\n :target: https://www.gnu.org/licenses/\n\n\nThis package is meant to build programatic hierarchical behaviors as graphs\nto compare them to human explanations of behavior.\n\nWe take the definition of \"behavior\" as a function from observation to action.\n\n\nInstallation\n------------\n\n\n.. code-block:: sh\n\n pip install hebg\n\n\nUsage\n-----\n\nBuild a HEBGraph\n~~~~~~~~~~~~~~~~\n\nHere is an example to show how could we hierarchicaly build an explanable behavior to pet a cat.\n\n.. code-block:: py3\n\n \"\"\"\n \n Here is the hierarchical structure that we would want:\n\n ```\n PetACat:\n IsThereACatAround ?\n -> Yes:\n PetNearbyCat\n -> No:\n LookForACat\n\n PetNearbyCat:\n IsYourHandNearTheCat ?\n -> Yes:\n Pet\n -> No:\n MoveYourHandNearTheCat\n ```\n\n \"\"\"\n\n from hebg import HEBGraph, Action, FeatureCondition, Behavior\n from hebg.unrolling import unroll_graph\n\n # Add a fundamental action\n class Pet(Action):\n def __init__(self) -> None:\n super().__init__(action=\"Pet\")\n\n # Add a condition on the observation\n class IsYourHandNearTheCat(FeatureCondition):\n def __init__(self, hand) -> None:\n super().__init__(name=\"Is hand near the cat ?\")\n self.hand = hand\n def __call__(self, observation):\n # Could be a very complex function that returns 1 is the hand is near the cat else 0.\n if observation[\"cat\"] == observation[self.hand]:\n return int(True) # 1\n return int(False) # 0\n\n # Add an unexplainable Behavior (without a graph, but a function that can be called).\n class MoveYourHandNearTheCat(Behavior):\n def __init__(self) -> None:\n super().__init__(name=\"Move slowly your hand near the cat\")\n def __call__(self, observation, *args, **kwargs) -> Action:\n # Could be a very complex function that returns actions from any given observation\n return Action(\"Move hand to cat\")\n\n # Add a sub-behavior\n class PetNearbyCat(Behavior):\n def __init__(self) -> None:\n super().__init__(name=\"Pet nearby cat\")\n def build_graph(self) -> HEBGraph:\n graph = HEBGraph(self)\n is_hand_near_cat = IsYourHandNearTheCat(hand=\"hand\")\n graph.add_edge(is_hand_near_cat, MoveYourHandNearTheCat(), index=int(False))\n graph.add_edge(is_hand_near_cat, Pet(), index=int(True))\n return graph\n\n # Add an other condition on observation\n class IsThereACatAround(FeatureCondition):\n def __init__(self) -> None:\n super().__init__(name=\"Is there a cat around ?\")\n def __call__(self, observation):\n # Could be a very complex function that returns 1 is there is a cat around else 0.\n if \"cat\" in observation:\n return int(True) # 1\n return int(False) # 0\n\n # Add an other unexplainable Behavior (without a graph, but a function that can be called).\n class LookForACat(Behavior):\n def __init__(self) -> None:\n super().__init__(name=\"Look for a nearby cat\")\n def __call__(self, observation, *args, **kwargs) -> Action:\n # Could be a very complex function that returns actions from any given observation\n return Action(\"Move to a cat\")\n\n # Finally, add the main Behavior\n class PetACat(Behavior):\n def __init__(self) -> None:\n super().__init__(name=\"Pet a cat\")\n def build_graph(self) -> HEBGraph:\n graph = HEBGraph(self)\n is_a_cat_around = IsThereACatAround()\n graph.add_edge(is_a_cat_around, LookForACat(), index=int(False))\n graph.add_edge(is_a_cat_around, PetNearbyCat(), index=int(True))\n return graph\n\n if __name__ == \"__main__\":\n pet_a_cat_behavior = PetACat()\n observation = {\n \"cat\": \"sofa\",\n \"hand\": \"computer\",\n }\n\n # Call on observation\n action = pet_a_cat_behavior(observation)\n print(action) # Action(\"Move hand to cat\")\n\n # Obtain networkx graph\n graph = pet_a_cat_behavior.graph\n print(list(graph.edges(data=\"index\")))\n\n # Draw graph using matplotlib\n import matplotlib.pyplot as plt\n fig, ax = plt.subplots()\n graph.draw(ax)\n plt.show()\n\n\n.. image:: docs/images/PetACatGraph.png\n :align: center\n\nUnrolling HEBGraph\n~~~~~~~~~~~~~~~~~~\n\nWhen ploting an HEBGraph of a behavior, only the graph of the behavior itself is shown.\nTo see the full hierarchical graph (including sub-behaviors), we need to unroll the graph as such:\n\n.. code-block:: py3\n\n from hebg.unrolling import unroll_graph\n\n unrolled_graph = unroll_graph(pet_a_cat_behavior.graph, add_prefix=False)\n \n # Is also a networkx graph\n print(list(unrolled_graph.edges(data=\"index\")))\n\n # Draw graph using matplotlib\n import matplotlib.pyplot as plt\n fig, ax = plt.subplots()\n unrolled_graph.draw(ax)\n plt.show()\n\n\n.. image:: docs/images/PetACatGraphUnrolled.png\n :align: center\n\nNote that unexplainable behaviors (the one without graphs) are kept as is.\n\nPython code generation from graph\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOnce you have a HEBGraph, you can use it to generate a working python code that\nreplicates the HEBGraph's behavior:\n\n.. code-block:: py3\n\n code = pet_a_cat_behavior.graph.generate_source_code()\n with open(\"pet_a_cat.py\", \"w\") as pyfile:\n pyfile.write(code)\n\nWill generate the code bellow:\n\n.. code-block:: py3\n\n from hebg.codegen import GeneratedBehavior\n\n # Require 'Look for a nearby cat' behavior to be given.\n # Require 'Move slowly your hand near the cat' behavior to be given.\n class PetTheCat(GeneratedBehavior):\n def __call__(self, observation):\n edge_index = self.feature_conditions['Is there a cat around ?'](observation)\n if edge_index == 0:\n return self.known_behaviors['Look for a nearby cat'](observation)\n if edge_index == 1:\n edge_index_1 = self.feature_conditions['Is hand near the cat ?'](observation)\n if edge_index_1 == 0:\n return self.known_behaviors['Move slowly your hand near the cat'](observation)\n if edge_index_1 == 1:\n return self.actions['Action(Pet)'](observation)\n\n\nContributing to HEBG\n--------------------\n\nWhenever you encounter a :bug: **bug** or have :tada: **feature request**, \nreport this via `Github issues <https://github.com/IRLL/HEB_graphs/issues>`_.\n\nIf you wish to contribute directly, see `CONTRIBUTING <https://github.com/IRLL/HEB_graphs/blob/main/CONTRIBUTING.rst>`_\n",
"bugtrack_url": null,
"license": "GPLv3 license",
"summary": "HEBG: Hierarchial Explainations of Behavior as Graph",
"version": "0.2.4",
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "b8ee82efcfeec89040fc768d398bda48c16ca9b9c45ed003d6cfb7670feef52d",
"md5": "f1525af4e9083a4bc8b075bc659d2d64",
"sha256": "1097c78d16b000d2ea0bf357dbcc2c6dbce9f781e843089c1a85f4094012d3f2"
},
"downloads": -1,
"filename": "hebg-0.2.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f1525af4e9083a4bc8b075bc659d2d64",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 41594,
"upload_time": "2023-02-04T19:18:21",
"upload_time_iso_8601": "2023-02-04T19:18:21.973811Z",
"url": "https://files.pythonhosted.org/packages/b8/ee/82efcfeec89040fc768d398bda48c16ca9b9c45ed003d6cfb7670feef52d/hebg-0.2.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "691ddc979fb1d9210cbbac9aacd4e7e7e90880c700823ac0bda9e06f4cc21be0",
"md5": "cb362ada132c64d32a7a736090080404",
"sha256": "d756f3f856e768454b8974f57ae8ccc3c96f00197354e79138eb1d560b327e34"
},
"downloads": -1,
"filename": "hebg-0.2.4.tar.gz",
"has_sig": false,
"md5_digest": "cb362ada132c64d32a7a736090080404",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 134631,
"upload_time": "2023-02-04T19:18:23",
"upload_time_iso_8601": "2023-02-04T19:18:23.892919Z",
"url": "https://files.pythonhosted.org/packages/69/1d/dc979fb1d9210cbbac9aacd4e7e7e90880c700823ac0bda9e06f4cc21be0/hebg-0.2.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-02-04 19:18:23",
"github": false,
"gitlab": false,
"bitbucket": false,
"lcname": "hebg"
}