{ "info": { "author": "Enrique P\u00e9rez Arnaud", "author_email": "enrique@cazalla.net", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "=============\nSyntreenet\n=============\n\nFree logics from PEGs\n---------------------\n\nSyntreenet facilitates easy development of any finite domain formal\ntheory possible in any language described by a `Parsing Expression Grammar`_.\n\nIt provides a knowledge base in the form of a performant and scalable\n`production system`_, where rules and facts interact to produce new rules and\nfacts. Facts in this context are the top productions in the provided PEGs, and\nrules are fundamentally composed of a set of those facts as conditions and\nanother set of facts as consecuences.\n\nIt's only dependence is on the excellent Parsimonious_ PEG parser by Erik Rose.\n\n.. contents::\n\nExample Usage\n-------------\n\nLet's start with a simple grammar with which we can build triples consisting on\na subject, a predicate, and an object, with 2 predicates, |element| and\n|subset|, thus producing classifications of things. To make this example\nsimpler, we will use the ASCII string \"element-of\" in place of unicode |element|,\nand \"subset-of\" in place of |subset|.\n\nThe grammar for this might be something like::\n\n fact = word ws pred ws word\n pred = element / subset\n element = \"element-of\"\n subset = \"subset-of\"\n word = ~\"[a-z0-9]+\"\n ws = ~\"\\s+\"\n\nWith this, we can have facts such as::\n\n a element-of b\n b subset-of c\n c subset-of d\n\nOn top of this language, we might want a logic where, if the previous 3\nfacts are added to a knowledge base, it would also have that::\n\n a element-of c\n a element-of d\n b subset-of d\n\nFor this, we need a logic in which variables range over the \"word\" productions.\nSo we modify the grammar substituting the \"word\" rule with::\n\n word = v_word / __var__\n v_word = ~\"[a-z0-9]+\"\n\nWith this grammar we can now build a knowledge base, and add rules appropriate\nfor our purposes:\n\n.. code:: python\n\n >>> from syntreenet import KnowledgeBase\n\n >>> grammar = \"\"\"\n >>> fact = word ws pred ws word\n >>> pred = element / subset\n >>> element = \"element-of\"\n >>> subset = \"subset-of\"\n >>> word = v_word / __var__\n >>> v_word = ~\"[a-z0-9]+\"\n >>> ws = ~\"\\s+\"\n >>> \"\"\"\n\n >>> kb = KnowledgeBase(grammar)\n\n >>> kb.tell(\"X1 element-of X2 ; X2 subset-of X3 -> X1 element-of X3\")\n >>> kb.tell(\"X1 subset-of X2 ; X2 subset-of X3 -> X1 subset-of X3\")\n\nNow we can add facts to the knowledge base, and query for them or for their\nconscuences:\n\n.. code:: python\n\n >>> kb.tell(\"a element-of b\")\n >>> kb.tell(\"b subset-of c\")\n >>> kb.tell(\"c subset-of d\")\n\n >>> kb.query(\"a element-of b\")\n True\n >>> kb.query(\"a element-of d\")\n True\n >>> kb.query(\"c element-of d\")\n False\n >>> kb.query(\"X1 subset-of d\")\n [{'X1': 'b'}, {'X1': 'c'}]\n\nGoals\n-----\n\nScalability:\n Adding new facts or rules is essentially O(1) in the number of rules plus\n facts already present in the knowledge base. Theoretically, this is due to\n the fact that the DAGs that hold the data (facts and rules) are only ever\n searched by consulting Python_ dictionaries. Practically, I am getting a\n fairly constant value of a couple tenths of a millisecond per fact (this\n will depend on the complexity of the grammar), up to the capacity of my\n laptop (totalling around 2 million facts and rules). \n\nUniversality:\n The \"free\" in the heading caption is in the sense of a `free object`_ over\n the formal languages described by PEGs: syntreenet knows nothing about the\n grammar underlying the particular logic it deals with at any particular\n moment.\n\nClear and tested code:\n The code follows best practices for readability and is tested with 99%\n coverage including branch analysis.\n\nDetailed Usage\n--------------\n\nInstall\n.......\n\nsyntreenet_ is available at pypi_, just use pip in a Python >= 3.7\nenvironment::\n\n $ pip install syntreenet\n $ python\n >>> import syntreenet\n\nTest\n....\n\nTo run the tests, you can download the sources from a mirror, create a Python_\nenvironment for it, and use nose2_::\n\n $ git clone https://git.sr.ht/~enriquepablo/syntreenet\n $ cd syntreenet/\n $ virtualenv venv\n $ source venv/bin/activate\n $ python setup.py develop easy_install syntreenet[testing]\n $ nose2\n\nGrammar requirements\n....................\n\nNote that these requirements can be overridden in the ``__init__`` method for\n``KnowledgeBase``.\n\n* The top production in the grammar must be called \"fact\".\n* The productions that must be in the range of the logical variables must have\n a name starting with ``\"v_\"``.\n* These \"logical\" productions must happen in higher productions as alternatives\n to the builtin production \"__var__\".\n* To make rules, 2 sets of facts (the conditions and the consecuences) must be\n joined by semicolons, and joined among them with the string \" -> \".\n* Only conditions, consecuences, and queries can have variables in place of\n \"logical\" productions. Facts cannot.\n* No grammar production can have a name starting and ending with 2 underscores.\n\n* Variables start with an \"X\", followed by any number of digits.\n\nBasic API\n.........\n\nThe API is extremelly simple. As seen above, the entry point for syntreenet is\nthe ``KnowledgeBase`` class. It is instantiated with a string containing a PEG\nappropriate for Parsimonious_ and subject to the restrictions stated above.\n\nObjects of this class offer 3 methods:\n\n* ``tell(self, sentence)``: accepts a fact or a rule in the form of a string and\n incorporates it to the knowledge base.\n* ``query(self, fact)``: accepts a fact (possibly with variables) in the form of a string,\n and returns whether the fact can be found in the knowledge base. If it has\n variables, it will return the variable substitutions that result in facts\n present in the knowledge base, in the form of a dict of strings to strings.\n* ``goal(self, fact)``: provided with a fact, it will return the facts that would be needed\n to get it to the knowledge base (without directly adding it). This is a form\n of backward chaining.\n\n\n\nCopyright (c) 2019 by Enrique P\u00e9rez Arnaud \n\n.. |element| unicode:: U+02208 .. element sign\n.. |subset| unicode:: U+02286 .. subset sign\n\n.. _syntreenet: http://www.syntree.net/\n.. _GPLv3: https://www.gnu.org/licenses/gpl-3.0.txt\n.. _pypi: https://pypi.org/project/syntreenet/\n.. _`production system`: https://en.wikipedia.org/wiki/Production_system_%28computer_science%29\n.. _`Parsing Expression Grammar`: https://en.wikipedia.org/wiki/Parsing_expression_grammar\n.. _Python: http://www.python.org/\n.. _syntreenet.scripts: https://git.sr.ht/~enriquepablo/syntreenet/tree/master/src/syntreenet/scripts/\n.. _Parsimonious: https://github.com/erikrose/parsimonious\n.. _nose2: https://docs.nose2.io/en/latest/\n.. _`free object`: https://en.wikipedia.org/wiki/Free_object", "description_content_type": "text/x-rst", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://www.syntree.net/", "keywords": "", "license": "GPLv3", "maintainer": "", "maintainer_email": "", "name": "syntreenet", "package_url": "https://pypi.org/project/syntreenet/", "platform": "", "project_url": "https://pypi.org/project/syntreenet/", "project_urls": { "Homepage": "http://www.syntree.net/" }, "release_url": "https://pypi.org/project/syntreenet/1.0.0b5/", "requires_dist": null, "requires_python": "", "summary": "A library to develop scalable production rule systems for any parsing expression grammar", "version": "1.0.0b5" }, "last_serial": 5640557, "releases": { "0.1.0a1": [ { "comment_text": "", "digests": { "md5": "eef48d854de7e748a91b962af9ef2bc4", "sha256": "2b16cdd220610e23d7a87f884c288d19a212d81e275b054453efb522038e9f47" }, "downloads": -1, "filename": "syntreenet-0.1.0a1.tar.gz", "has_sig": false, "md5_digest": "eef48d854de7e748a91b962af9ef2bc4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11607, "upload_time": "2019-07-06T17:21:38", "url": "https://files.pythonhosted.org/packages/09/d2/6e7c1ddb0c1d3558ee8263ef70ec6e326eca88b71a0015db4a25f6dc2c99/syntreenet-0.1.0a1.tar.gz" } ], "0.1.0a11": [ { "comment_text": "", "digests": { "md5": "e0dcb9f4e47fb4e090b4d7c558a45e8c", "sha256": "08db7754a41ab0b50e6ae4acedf4c8b49b0edd8f43d479bda5fce743ebfda277" }, "downloads": -1, "filename": "syntreenet-0.1.0a11-py3-none-any.whl", "has_sig": false, "md5_digest": "e0dcb9f4e47fb4e090b4d7c558a45e8c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 45471, "upload_time": "2019-07-06T19:11:09", "url": "https://files.pythonhosted.org/packages/d5/12/acaff099c0ce4c590ee6978b8d9a4152b0a66e2a285780d9136cd3de6f1a/syntreenet-0.1.0a11-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9d05028642529e94bd53b04c00821f99", "sha256": "4049561c7fc8e77b6fe639ebe0d673201e63ecae2088f9fefc62b4edd456068d" }, "downloads": -1, "filename": "syntreenet-0.1.0a11.tar.gz", "has_sig": false, "md5_digest": "9d05028642529e94bd53b04c00821f99", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29457, "upload_time": "2019-07-06T19:11:11", "url": "https://files.pythonhosted.org/packages/8d/0a/67d7599f85861bbad7ab22b19b4bccc53d6365299d331e2d1fe4a7931e48/syntreenet-0.1.0a11.tar.gz" } ], "0.1.0a9": [ { "comment_text": "", "digests": { "md5": "7aa2486c5089af66b2980fec2255815e", "sha256": "1b961c5667fa05b85596c71517ff4c5afa603f6362112563107eba052866b6b8" }, "downloads": -1, "filename": "syntreenet-0.1.0a9-py3-none-any.whl", "has_sig": false, "md5_digest": "7aa2486c5089af66b2980fec2255815e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 27136, "upload_time": "2019-07-06T18:07:50", "url": "https://files.pythonhosted.org/packages/45/7e/bc56024cffde8982d6480e1ede63ce50b3b9ab99e4ba3b4274ffff0a8b3a/syntreenet-0.1.0a9-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4f5286e2b715cf15912ac42a04dad8c1", "sha256": "87d0eafd1e197bbe452db1a71b155619aca42572e6142d264d7460d298122751" }, "downloads": -1, "filename": "syntreenet-0.1.0a9.tar.gz", "has_sig": false, "md5_digest": "4f5286e2b715cf15912ac42a04dad8c1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21390, "upload_time": "2019-07-06T18:07:52", "url": "https://files.pythonhosted.org/packages/5e/77/f00184dfb85f29c7f75ad78c78a2a860f9c35cb47e94ba33e2427f2fc496/syntreenet-0.1.0a9.tar.gz" } ], "1.0.0b2": [ { "comment_text": "", "digests": { "md5": "42c2dca47df0d6a9b0383fecec1b7475", "sha256": "69f112e5ce6fe85f31385911c85d51c33f68b3d2b088b338325cff2ecf947258" }, "downloads": -1, "filename": "syntreenet-1.0.0b2.tar.gz", "has_sig": false, "md5_digest": "42c2dca47df0d6a9b0383fecec1b7475", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31924, "upload_time": "2019-08-05T18:34:07", "url": "https://files.pythonhosted.org/packages/00/2a/edf41a17ed2e30ba1370c8c6bae22b16bac15d684f1ef883f8413b9219c4/syntreenet-1.0.0b2.tar.gz" } ], "1.0.0b4": [ { "comment_text": "", "digests": { "md5": "ac20fe8e3fc3cf5ba7de4ad6165a2506", "sha256": "61fd569612f2fd01880105205d2f40956557de790a320149d9b421ba16503201" }, "downloads": -1, "filename": "syntreenet-1.0.0b4.tar.gz", "has_sig": false, "md5_digest": "ac20fe8e3fc3cf5ba7de4ad6165a2506", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32447, "upload_time": "2019-08-05T20:30:26", "url": "https://files.pythonhosted.org/packages/f4/a7/69983a07f4fe2a45a5ea8026c6542e7cc9f8644a1e9bc52c58af257736a3/syntreenet-1.0.0b4.tar.gz" } ], "1.0.0b5": [ { "comment_text": "", "digests": { "md5": "37586ecd7604f3e781ad7b7d357d86ef", "sha256": "206551ce50d6c100c627008d598bbb7a132dc7ab78c85c103bdd4416b4aff9cc" }, "downloads": -1, "filename": "syntreenet-1.0.0b5.tar.gz", "has_sig": false, "md5_digest": "37586ecd7604f3e781ad7b7d357d86ef", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32519, "upload_time": "2019-08-06T15:52:17", "url": "https://files.pythonhosted.org/packages/43/0d/11e7bb199bdb61be410c403908d05532bdd90bfeb0228ca114c0ff91f4aa/syntreenet-1.0.0b5.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "37586ecd7604f3e781ad7b7d357d86ef", "sha256": "206551ce50d6c100c627008d598bbb7a132dc7ab78c85c103bdd4416b4aff9cc" }, "downloads": -1, "filename": "syntreenet-1.0.0b5.tar.gz", "has_sig": false, "md5_digest": "37586ecd7604f3e781ad7b7d357d86ef", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32519, "upload_time": "2019-08-06T15:52:17", "url": "https://files.pythonhosted.org/packages/43/0d/11e7bb199bdb61be410c403908d05532bdd90bfeb0228ca114c0ff91f4aa/syntreenet-1.0.0b5.tar.gz" } ] }