https://github.com/bedus-creation/automata
https://github.com/bedus-creation/automata
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/bedus-creation/automata
- Owner: bedus-creation
- Created: 2026-03-07T01:03:27.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-03-07T01:23:50.000Z (5 months ago)
- Last Synced: 2026-03-07T08:22:37.321Z (5 months ago)
- Language: HTML
- Size: 309 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
# Finite State Machine (FSM)
A generic, reusable, and fluent object-oriented Finite State Machine library implementation in PHP.
This library makes it simple to map mathematical Final Automata logic (with states, inputs, and transitions) directly to robust software.
## Setup and Execution
### Requirements
- PHP 8.3 or higher
- Composer
### Installation
1. Clone the repository to your local machine:
```bash
git clone git@github.com:bedus-creation/automata.git
```
2. Navigate to the project directory and install dependencies via Composer:
```bash
composer install
```
3. Run the `index.php` file to execute the Finite State Machine example for modulo three Example:
```bash
php index.php
```
### Running Tests
The project includes a comprehensive suite of Unit and Integration (as well as Benchmark) tests using PHPUnit.
To execute the tests:
```bash
composer test
```
To run tests with code coverage (requires Xdebug or PCOV):
```bash
composer coverage
```
### Code Quality (Static Analysis & Formatting)
The project is configured with PHPStan (Level 8) and Pint to ensure high code quality.
To analyze the codebase:
```bash
composer analyze
```
To automatically format code to adhere to PSR-12 and formatting rules:
```bash
composer format
```
## Features
- Fully fluent API.
- Closures for flexible state declaration.
- Stores custom data on States for easy result extraction.
- Multibyte sequence (unicode) support (e.g. emojis).
- Validation and Transition Error checking.
## Usage Example: Modulo Three
Here is how you would configure the FSM to evaluate a binary string and find the integer remainder when divided by 3:
```php
use App\FSM;
use App\State;
// 1. Initialize the FSM and define allowed inputs
$fsm = (new FSM())->setInputs(['0', '1']);
// 2. Add states and map out their inputs -> transition targets
$s0 = new State($fsm, 'S0');
$s1 = new State($fsm, 'S1');
$s2 = new State($fsm, 'S2');
// Add transitions
$s0->addTransition('0', $s0)
->addTransition('1', $s1);
$s1->addTransition('0', $s2)
->addTransition('1', $s0);
$s2->addTransition('0', $s1)
->addTransition('1', $s2);
// Set initial state, final states, and add states
$fsm->addState($s0)
->addState($s1)
->addState($s2);
$fsm->setInitialState($s0);
$fsm->addAcceptingStates($s0);
// 3. Process the entire sequence with `run()`
$fsm->run('1101'); // 13 in decimal
// 4. Retrieve the answer current states from the FSM
echo $fsm->currentState; // Outputs S1
```
## State's data
We can attach data of any type to a stage.
```php
$s0->setData(0);
$s1->setData(0);
$s2->setData(1);
// 3. Process the entire sequence with `run()`
$fsm->run('1101'); // 13 in decimal
// 4. Retrieve the data from current state
echo $fsm->currentState->data; // Outputs 1
```
## Dynamic State Creation
By default, the FSM requires states to be explicitly registered via instantiated `State` objects. `addState()` and `findState()` and throws exceptions if the state doesn't exist.
You can enable dynamic state creation by using the `enableDynamicStates()` flag. This allows the FSM to automatically create any target states that don't exist yet, which is incredibly useful when using closures to map out transitions:
```php
$fsm = new FSM();
$fsm->enableDynamicStates();
$fsm->setInputs(['0', '1']);
$fsm->addState('A', function (State $state) {
$state->setIsInitialState();
$state->addTransition('0', 'B'); // 'B' will be dynamically created!
});
$fsm->addState('B', function (State $state) {
$state->addTransition('1', 'A');
});
$fsm->run('010');
echo $fsm->currentState->name; // Outputs 'B'
```
## Unicode and Multibyte Support
This system naturally supports any multibyte Unicode characters, making it quite flexible for text tokenizing or complex emoji state handling:
```php
$fsm = new FSM();
$fsm->enableDynamicStates();
$fsm->setInputs(['😎', '🔥']);
$fsm->addState('Cool State', function(State $state) {
$state->setIsInitialState();
$state->addTransition('😎', 'Fire State');
});
$fsm->addState('Fire State', function(State $state) {
$state->addTransition('🔥', 'Cool State');
});
$fsm->run('😎🔥😎');
echo $fsm->currentState->name; // Outputs 'Fire State'
```
## Re-using without Rebuilding
You don't need to rebuild the object every time you evaluate a sequence! You can just call `reset()`:
```php
$fsm->run('1101');
echo $fsm->currentState->data; // 1
$fsm->reset();
$fsm->run('1111');
echo $fsm->currentState->data; // 0
```
## Performance / Benchmarks
The library is designed to be lightweight and fast. As proven by the included benchmark test suite (`tests/Benchmark/FSMPerformanceTest.php`), an FSM instance can process an input sequence of **500,000 characters** (half a million transitions) in roughly **~0.4 seconds** depending on the hardware.
This makes it extremely scalable for evaluating huge text blocks, bitwise sequences, or high-volume streams perfectly matching the mathematical logic without overhead.