hebg


Namehebg JSON
Version 0.2.4 PyPI version JSON
download
home_page
SummaryHEBG: Hierarchial Explainations of Behavior as Graph
upload_time2023-02-04 19:18:23
maintainer
docs_urlNone
authorMathïs Fédérico
requires_python>=3.7
licenseGPLv3 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&amp;utm_medium=referral&amp;utm_content=IRLL/HEB_graphs&amp;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&amp;utm_medium=referral&amp;utm_content=IRLL/HEB_graphs&amp;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"
}
        
Elapsed time: 0.07531s