Skip to main content

dfa-identify

Python library for identifying (learning) minimal DFAs from labeled examples by reduction to SAT.

Build Status PyPI version License: MIT

Table of Contents

Installation

If you just need to use dfa, you can just run:

$ pip install dfa

For developers, note that this project uses the poetry python package/dependency management tool. Please familarize yourself with it and then run:

$ poetry install

Usage

dfa_identify is centered around the find_dfa and find_dfas function. Both take in sequences of accepting and rejecting "words", where are word is a sequence of arbitrary python objects.

  1. find_dfas returns all minimally sized (no DFAs exist of size smaller) consistent with the given labeled data.

  2. find_dfa returns an arbitrary (first) minimally sized DFA.

The returned DFA object is from the dfa library.

from dfa_identify import find_dfa


accepting = ['a', 'abaa', 'bb']
rejecting = ['abb', 'b']
    
my_dfa = find_dfa(accepting=accepting, rejecting=rejecting)

assert all(my_dfa.label(x) for x in accepting)
assert all(not my_dfa.label(x) for x in rejecting)

Because words are sequences of arbitrary python objects, the identification problem, with a ↦ 0 and b ↦ 1, is given below:

accepting = [[0], [0, 'z', 0, 0], ['z', 'z']]
rejecting = [[0, 'z', 'z'], ['z']]

my_dfa = find_dfa(accepting=accepting, rejecting=rejecting)

Active learning

There are also active variants of find_dfa and find_dfas called find_dfa_active and find_dfas_active resp.

An example from the unit tests:

import dfa
from dfa_identify import find_dfa_active


def oracle(word):
    return sum(word) % 2 == 0

lang = find_dfa_active(alphabet=[0, 1],
                       oracle=oracle,
                       n_queries=20)
assert lang == dfa.DFA(
    inputs=[0,1],
    label=lambda s: s,
    transition=lambda s, c: s ^ bool(c),
    start=True
)

# Can also send in positive and negative examples:
lang = find_dfa_active(alphabet=[0, 1],
                       positive=[(0,), (0,0)],
                       negative=[(1,), (1,0)],
                       oracle=oracle,
                       n_queries=20)

Learning Decomposed DFAs

The is also support for learning decomposed DFAs following, Learning Deterministic Finite Automata Decompositions from Examples and Demonstrations. FMCAD`22. These are tuples of DFAs whose labels are combined to determine the acceptence / rejection of string, e.g., via conjunction or disjunction.

Similar to learning a monolithic dfa, this functionality can be accessed using find_decomposed_dfas. For example:

from dfa_identify import find_decomposed_dfas
accepting = ['y', 'yy', 'gy', 'bgy', 'bbgy', 'bggy']
rejecting = ['', 'r', 'ry', 'by', 'yr', 'gr', 'rr', 'rry', 'rygy']

# --------------------------------------
# 1. Learn a disjunctive decomposition.
# --------------------------------------
gen_dfas = find_decomposed_dfas(accepting=accepting,
                                rejecting=rejecting,
                                n_dfas=2,
                                order_by_stutter=True,
                                decompose_via="disjunction")
dfas = next(gen_dfas)

monolithic = dfas[0] | dfas[1]  # Build DFA that is the union of languages.
assert all(monolithic.label(w) for w in accepting)
assert not any(monolithic.label(w) for w in rejecting)

# Each dfa must reject a rejecting string.
assert all(all(~d.label(w) for d in dfas) for w in rejecting)
# At least one dfa must accept an accepting string.
assert all(any(d.label(w) for d in dfas) for w in accepting)

# --------------------------------------
# 2. Learn a conjunctive decomposition.
# --------------------------------------
gen_dfas = find_decomposed_dfas(accepting=accepting,
                                rejecting=rejecting,
                                n_dfas=2,
                                order_by_stutter=True,
                                decompose_via="conjunction")
dfas = next(gen_dfas)

monolithic = dfas[0] & dfas[1]  # Build DFA that is the union of languages.
assert all(monolithic.label(w) for w in accepting)
assert not any(monolithic.label(w) for w in rejecting)

Minimality

There are two forms of "minimality" supported by dfa-identify.

  1. By default, dfa-identify returns DFAs that have the minimum number of states required to seperate the accepting and rejecting set.
  2. If the order_by_stutter flag is set to True, then the find_dfas (lazily) orders the DFAs so that the number of self loops (stuttering transitions) appearing the DFAs decreases. find_dfa thus returns a DFA with the most number of self loops given the minimal number of states.

Encoding

This library currently uses the encodings outlined in Heule, Marijn JH, and Sicco Verwer. "Exact DFA identification using SAT solvers." International Colloquium on Grammatical Inference. Springer, Berlin, Heidelberg, 2010. and Ulyantsev, Vladimir, Ilya Zakirzyanov, and Anatoly Shalyto. "Symmetry Breaking Predicates for SAT-based DFA Identification.".

The key difference is in the use of the symmetry breaking clauses. Two kinds are exposed.

  1. clique (Heule 2010): Partially breaks symmetries by analyzing conflict graph.
  2. bfs (Ulyantsev 2016): Breaks all symmetries so that each model corresponds to a unique DFA.

Goals and related libraries

There are many other python libraries that perform DFA and other automata inference.

  1. DFA-Inductor-py - State of the art passive inference via reduction to SAT (as of 2019).
  2. z3gi: Uses SMT backed passive learning algorithm.
  3. lstar: Active learning algorithm based L* derivative.

The primary goal of this library is to loosely track the state of the art in passive SAT based inference while providing a simple implementation and API.

Metadata

Release files for dfa_identify 3.13.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dfa_identify 3.13.0
File Size Uploaded
dfa_identify-3.13.0.tar.gz 17.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dfa_identify 3.13.0
File Interpreter ABI Platform
dfa_identify-3.13.0-py3-none-any.whl Python 3 none any Details

Total release size: 37.6 kB

Release files / dfa_identify-3.13.0.tar.gz

Download URL dfa_identify-3.13.0.tar.gz
Size 17.9 kB
Tags Source
SHA-256 checksum
How to use checksums
8beec037b81e6c0f40c67fbf1c565dd0a3d4373300315eccee032744e0e6e13c
BLAKE2b-256 checksum
How to use checksums
2a3da6ff9c528291772412fc55abfa793cac5500aba741de2a62c6033287b4e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.8.2 CPython/3.11.8 Linux/6.6.19

Release files / dfa_identify-3.13.0-py3-none-any.whl

Download URL dfa_identify-3.13.0-py3-none-any.whl
Size 19.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4e701e25782d87ccf9c0d68f7d4bdac0f123d2bbed4c8dee1c0a2c706f5f6038
BLAKE2b-256 checksum
How to use checksums
7770022ca336f0a029ddb2525fe3de5f3f3cfdcf7a4800872d8c42d26f3b5566
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.8.2 CPython/3.11.8 Linux/6.6.19

Release history Release notifications | RSS feed

This release

3.13.0 This release

2 release files

3.12.0

2 release files

3.11.0

2 release files

3.10.2

2 release files

3.10.1

2 release files

3.10.0

2 release files

3.9.1

2 release files

3.9.0

2 release files

3.8.0

2 release files

3.7.2

2 release files

3.7.1

2 release files

3.7.0

2 release files

3.6.0

2 release files

3.5.0

2 release files

3.4.0

2 release files

3.3.0

2 release files

3.2.2

2 release files

3.2.1

2 release files

3.2.0

2 release files

3.1.3

2 release files

3.1.2

2 release files

3.1.1

2 release files

3.1.0

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.0.0

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page