{"id":38519308,"url":"https://github.com/mvcisback/lstar","last_synced_at":"2026-01-17T06:37:03.766Z","repository":{"id":49014033,"uuid":"181398024","full_name":"mvcisback/lstar","owner":"mvcisback","description":"Python implementation of lstar automata learning algorithm.","archived":false,"fork":false,"pushed_at":"2024-01-23T07:09:44.000Z","size":96,"stargazers_count":10,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-04T19:52:17.948Z","etag":null,"topics":["active-learning","automata","learning","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mvcisback.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-04-15T02:26:15.000Z","updated_at":"2025-06-21T06:06:48.000Z","dependencies_parsed_at":"2025-04-11T11:48:54.321Z","dependency_job_id":"30c91cd2-f5e2-4d75-b2ac-a48adceda6c2","html_url":"https://github.com/mvcisback/lstar","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mvcisback/lstar","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvcisback%2Flstar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvcisback%2Flstar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvcisback%2Flstar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvcisback%2Flstar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mvcisback","download_url":"https://codeload.github.com/mvcisback/lstar/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvcisback%2Flstar/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28502643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T04:31:57.058Z","status":"ssl_error","status_checked_at":"2026-01-17T04:31:45.816Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["active-learning","automata","learning","python"],"created_at":"2026-01-17T06:37:03.616Z","updated_at":"2026-01-17T06:37:03.748Z","avatar_url":"https://github.com/mvcisback.png","language":"Python","readme":"# L*\n\n[![Build Status](https://cloud.drone.io/api/badges/mvcisback/lstar/status.svg)](https://cloud.drone.io/mvcisback/lstar)\n[![codecov](https://codecov.io/gh/mvcisback/lstar/branch/master/graph/badge.svg)](https://codecov.io/gh/mvcisback/lstar)\n[![PyPI version](https://badge.fury.io/py/lstar.svg)](https://badge.fury.io/py/lstar)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nImplementation of the discriminant tree L* algorithm DFA learning algorithm\nprovided in [^1].\n\n\n\u003c!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-generate-toc again --\u003e\n**Table of Contents**\n\n- [Installation](#installation)\n- [Usage](#usage)\n    - [Label Queries](#label-queries)\n    - [Equivalence Queries](#equivalence-queries)\n    - [All together](#all-together)\n- [Learning Moore Machines and DFA-labelers](#learning-moore-machines-and-dfa-labelers)\n- [Testing](#testing)\n- [Footnotes](#footnotes)\n\n\u003c!-- markdown-toc end --\u003e\n\n\n\n# Installation\n\nIf you just need to use `lstar`, you can just run:\n\n`$ pip install lstar`\n\nFor developers, note that this project uses the\n[poetry](https://poetry.eustace.io/) python package/dependency\nmanagement tool. Please familarize yourself with it and then\nrun:\n\n`$ poetry install`\n\n# Usage\n\nThe main entry point for using this library is the `learn_dfa`\nfunction.\n\n```python\nfrom lstar import learn_dfa\n```\n\nThis function requires the arguments:\n```python\ndfa = learn_dfa(\n    inputs= .. ,  #  Inputs over which the target concept is over.\n                    #  Note: Sequence of Hashables.\n\n    label=..,  #  Function answering whether a given word is in the target\n                    #  language.\n                    #\n                    #  Tuple[Alphabet] -\u003e bool\n\n    find_counter_example=..,  #  Function which takes a hypothesis DFA\n                              #  and either returns None or a counter example,\n                              #  i.e., an element misclassified by hypothesis\n                              #  DFA.\n                              #\n                              #  DFA -\u003e Union[Tuple[Alphabet], None]\n\n)\n```\n\nBelow is an example of learning following language over `{0, 1}`:\n\n\n\u003e The number of 1's in the word is a multiple of 4.\n\n\n## Label Queries\n\nWe start by defining the label query function. \n\n**Note** that this implementation of `lstar` assumes that this\nfunction is either cheap (`O(1)`-ish) to call or is memoized.\n\n\n```python\nfrom functools import lru_cache\n\n@lru_cache(maxsize=None)  # Memoize member queries \ndef is_mult_4(word):\n    \"\"\"Want to learn 4 state counter\"\"\"\n    return (sum(word) % 4) == 0\n```\n\n## Equivalence Queries\n\nNext you need to define a function which given a candidate `DFA`\nreturns either a counter example that this `DFA` mislabels or `None`.\n\nNote that the `DFA` type used comes from the `dfa` package\n([link](https://github.com/mvcisback/dfa)).\n\n`lstar` provides two functions to make writing counterexample oracles \neasier.\n\n1. `validate_ce`: Takes a counterexample oracle and retries \n   if returned \"counterexample\" is not actually a counterexample.\n   Useful if using heuristic solver or asking a human.\n\n    ```python\n    from lstar import validate_ce\n\n    @validate_ce(is_mult_4, retry=True)\n    def ask_human(dfa):\n        ...\n    ```\n2. `iterative_deeping_ce`: This function performs an iterative\n   deepening traversal of the candidate dfa and see's if it matches\n   the labeler on all tested words.\n\n   ```python\n   from lstar import iterative_deeping_ce\n\n   find_ce = iterative_deeping_ce(is_mult_4, depth=10)\n   ```\n\n\n## All together\n\n```python\ndfa = learn_dfa(\n    inputs={0, 1},  #  Possible inputs.\n    label=is_mult_4,  #  Does this sequence belong in the language.\n    find_counter_example=iterative_deeping_ce(is_mult_4, depth=10)\n)\n\nassert not dfa.label(())\nassert not dfa.label((1,))\nassert not dfa.label((1, 1, ))\nassert dfa.label((1, 1, 1))\nassert dfa.label((1, 1, 0, 1))\n```\n\n# Learning Moore Machines and DFA-labelers\n\nBy default, `learn_dfa` learns as Deterministic Finite Acceptor;\nhowever, by specifying the `outputs` parameter and adjusting the\n`label` function, one can learn a Deterministic Finite Labeler\n(which is isomorphic to a Moore Machine). \n\nFor example, the 4 state counter from before can be modified to output\nthe current count rather than whether or not the word sums to a\nmultiple of 4.\n\n\n```python\ndef sum_mod_4(state):\n    return sum(state) % 4\n\ndfl = learn_dfa(\n    inputs={0, 1},\n    label=sum_mod_4,\n    find_counter_example=ask_human,\n    outputs={0, 1, 2, 3},\n)  # Returns a Deterministic Finite Labeler.\n\nassert dfl.label(()) == 0\nassert dfl.label((1,)) == 1\nassert dfl.label((1, 1, )) == 2\nassert dfl.label((1, 1, 1)) == 3\nassert dfl.label((1, 1, 0, 1)) == 3\nassert dfl.label((1, 1, 1, 1)) == 0\n```\n\nThe deterministic labeler can be interpreted as a moore machine by\nusing the `transduce` method rather than `label`.\n\n```python\nassert dfl.transduce(()) == ()\nassert dfl.transduce((1,)) == (0,)\nassert dfl.transduce((1, 1, )) == (0, 1)\nassert dfl.transduce((1, 1, 1)) == (0, 1, 2)\nassert dfl.transduce((1, 1, 0, 1)) == (0, 1, 2, 2)\nassert dfl.transduce((1, 1, 1, 1, 1)) == (0, 1, 2, 3, 0)\n```\n\n\n# Testing\n\nThis project uses pytest. Simply run\n\n`$ poetry run pytest`\n\nin the root of the repository.\n\n# Similar Libraries\n## Python Based\n    1. https://github.com/steynvl/inferrer : DFA learning\n       library supporting active and passive dfa learning. Active\n       learning is based on L* with an observation table. Also\n       supports learning NFAs.\n\n   1. https://gitlab.lis-lab.fr/dev/scikit-splearn/ : Library for learning\n      weighted automata via the spectral method.\n\n   1. https://pypi.org/project/pylstar/ : Another L* based DFA\n      learning library.\n\n## Java Based\n   1. https://learnlib.de/ : State of the art automata learning\n      toolbox. Supports passive and active learning algorithms for DFAs,\n      Mealy Machines, and Visibly Push Down Automata.\n   1. https://github.com/lorisdanto/symbolicautomata : Library for\n      symbolic automata and symbolic visibly pushdown automata.\n\n# Footnotes\n\n[^1]: Kearns, Michael J., Umesh Virkumar Vazirani, and Umesh Vazirani. An introduction to computational learning theory. MIT press, 1994.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmvcisback%2Flstar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmvcisback%2Flstar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmvcisback%2Flstar/lists"}