From 180bc8aa831c988d1b6ee82178bb23acd5c1b2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Bohn?= Date: Thu, 30 Oct 2025 22:24:05 +0100 Subject: [PATCH 1/2] WIP remove some stuff --- bench/.gitignore | 2 -- bench/Cargo.toml | 18 ------------ bench/src/main.rs | 67 ------------------------------------------ benchmarks.csv | 4 --- bin/incong/Cargo.toml | 11 ------- bin/incong/src/main.rs | 43 --------------------------- perf | 65 ---------------------------------------- 7 files changed, 210 deletions(-) delete mode 100644 bench/.gitignore delete mode 100644 bench/Cargo.toml delete mode 100644 bench/src/main.rs delete mode 100644 benchmarks.csv delete mode 100644 bin/incong/Cargo.toml delete mode 100644 bin/incong/src/main.rs delete mode 100755 perf diff --git a/bench/.gitignore b/bench/.gitignore deleted file mode 100644 index a3576ab..0000000 --- a/bench/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -built-automata-benchmarks* -Cargo.toml.bak diff --git a/bench/Cargo.toml b/bench/Cargo.toml deleted file mode 100644 index 38d6613..0000000 --- a/bench/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "automata-benchmarks" -version = "0.1.0" -edition = "2021" - -[dependencies] -automata = { path="../automata" } -# automata = { git = "https://github.com/leonbohn/automata", rev = "48b84ff" } - -[features] -commit_0 = [] -commit_1 = [] -commit_2 = [] -commit_3 = [] -commit_4 = [] - -[profile.release] -debug = true diff --git a/bench/src/main.rs b/bench/src/main.rs deleted file mode 100644 index 66e56a4..0000000 --- a/bench/src/main.rs +++ /dev/null @@ -1,67 +0,0 @@ -#[cfg(feature = "commit_4")] -use packed::{Id, Packed, PackedEdge}; - -fn runs() { - #[cfg(not(feature = "commit_4"))] - let ts = DTS::builder() - .default_color(Void) - .with_transitions([ - (0, 'a', 1), - (0, 'b', 0), - (1, 'a', 2), - (1, 'b', 1), - (2, 'a', 3), - (2, 'b', 1), - (3, 'a', 1), - (3, 'b', 0), - ]) - .into_dts_with_initial(0); - - #[cfg(feature = "commit_4")] - let ts = Packed::new( - CharAlphabet::of_size(2), - vec![Some(Void), Some(Void), Some(Void), Some(Void)], - [].into_iter() - .map(|(q, a, p)| PackedEdge::new(q, p, a, Void)) - .collect(), - ) - .with_initial(Id(0)); - - let words = vec![ - upw!("abba"), - upw!("babbabba", "bababbabbabbba"), - upw!("aa"), - upw!("babbabba", "babbaaaaaaaaaaaa"), - upw!("bbababaaaaba"), - upw!("babbabba", "babbbababaabbabbba"), - upw!("abba"), - upw!("aba"), - upw!("abaaabababababababbababbababba"), - upw!("babbabba", "bababbabbabbbababbabaa"), - ]; - let mut size: u128 = 0; - for i in 0..5000 { - for word in &words { - #[cfg(feature = "commit_4")] - let infset = ts.recurrent_state_indices_from(Id(i % 4), word).unwrap(); - #[cfg(feature = "commit_3")] - let infset = ts.recurrent_state_indices_from(i as u32 % 4, word).unwrap(); - #[cfg(feature = "commit_2")] - let infset = ts.recurrent_state_indices_from(i as u32 % 4, word).unwrap(); - #[cfg(feature = "commit_1")] - let infset = ts.recurrent_state_indices_from(i as u32 % 4, word).unwrap(); - #[cfg(feature = "commit_0")] - let infset = ts - .recurrent_state_indices_from(i as u32 % 4, word) - .unwrap() - .collect::>(); - size += infset.len() as u128; - size = size % 1337; - size += (4 << 2) ^ ((4815 + 1623) % 42) - } - } -} - -fn main() { - runs() -} diff --git a/benchmarks.csv b/benchmarks.csv deleted file mode 100644 index be38944..0000000 --- a/benchmarks.csv +++ /dev/null @@ -1,4 +0,0 @@ -command,mean,stddev,median,user,system,min,max -./bench/built-automata-benchmarks-0-48b84ff,0.06705744223000001,0.0009918095709769588,0.06676731988000001,0.06252972,0.0022978899999999995,0.06539972888000001,0.06935793488 -./bench/built-automata-benchmarks-1-650c51c,0.10157253393000001,0.0011336889909546813,0.10164798638,0.09704652,0.00226629,0.09949059588,0.10412300088000001 -./bench/built-automata-benchmarks-latest,0.04754331873000001,0.0022300958565742417,0.047032282380000005,0.04332337,0.00217694,0.044913407880000006,0.05578250188 diff --git a/bin/incong/Cargo.toml b/bin/incong/Cargo.toml deleted file mode 100644 index a1d2ad7..0000000 --- a/bin/incong/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "incong" -version = "0.1.0" -edition = "2024" - -[dependencies] -tracing = { workspace = true } -tracing-subscriber = { workspace = true } -itertools = { workspace = true } - -automata = { path = "../../crates/automata" } diff --git a/bin/incong/src/main.rs b/bin/incong/src/main.rs deleted file mode 100644 index 92fb30d..0000000 --- a/bin/incong/src/main.rs +++ /dev/null @@ -1,43 +0,0 @@ -use automata::core::alphabet::{FreeMonoid, Symbol}; -use automata::core::word::{PeriodicOmegaWord, Rotate}; - -fn compute(symbols: Vec, max_length: usize) -> (Vec>, usize) { - let mut unique = Vec::new(); - let mut neg = 0; - - 'outer: for w in FreeMonoid::non_empty(symbols) { - if w.len() >= max_length { - break; - } - let periodic = PeriodicOmegaWord::new(w); - - if unique.contains(&periodic) { - neg += 1; - continue 'outer; - } - - for rot in periodic.rotations() { - let periodic = PeriodicOmegaWord::new(rot); - if unique.contains(&periodic) { - neg += 1; - continue 'outer; - } - } - unique.push(periodic); - } - (unique, neg) -} - -fn main() { - let symbols = vec!['a', 'b', 'c', 'd', 'e', 'f', 'g']; - - for i in 2..10 { - let (unique, neg) = compute(symbols.clone(), i); - println!( - "length {i}\n{} | {} that is {}%", - unique.len(), - neg, - 100.0 * unique.len() as f64 / (neg as f64 + unique.len() as f64) - ) - } -} diff --git a/perf b/perf deleted file mode 100755 index 6a23c30..0000000 --- a/perf +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash -set -e - -RESULTS_FILE="benchmarks.txt"#${1:-"benchmarks.txt"} -commit_hashes=( - "48b84ff" - "b04e0a9" - "a723cee" -) -echo "Benchmarking for commit hashes: ${commit_hashes[@]}" > $RESULTS_FILE - -CARGO_TOML="$(pwd)/bench/Cargo.toml" - -# Function to update the Cargo.toml with a given commit hash -update_cargo_toml() { - local commit_hash=$1 - sed -i.bak "s/^automata = { .* }$/automata = { git = \"https:\/\/github.com\/leonbohn\/automata\", rev = \"$commit_hash\" }/" $CARGO_TOML -} - -# Function to build the binary -build_binary() { - local feature=$1 - local hash=$2 - cargo build --release --features "commit_$feature" --manifest-path $CARGO_TOML 2>&1 > /dev/null - if [ $? -ne 0 ]; then - echo -e "\033[31m Build failed for commit $hash\033[30m" - exit 1 - fi -} - -flamegraph() { - local feature=$1 - cargo flamegraph --release --features "commit_$feature" --manifest-path $CARGO_TOML - cp ./bench/flamegraph.svg ./bench/flamegraph_$feature.svg -} - - -# Clear previous results -echo -e "\033[34mBenchmarking Results\033[0m" > $RESULTS_FILE - -# Loop over all commit hashes -for i in "${!commit_hashes[@]}"; do - commit_hash=${commit_hashes[$i]} - if [ -f "./bench/built-automata-benchmarks-$i-$commit_hash" ]; then - echo -e "\033[34mBinary for commit ${commit_hashes[$i]} already exists\033[0m" - continue - fi - echo -e "\033[34mBuilding binary for commit ${commit_hashes[$i]}\033[0m" - - # Update the Cargo.toml with the new commit hash - update_cargo_toml $commit_hash - - # Build the binary - build_binary $i $commit_hash - cp ./bench/target/release/automata-benchmarks ./bench/built-automata-benchmarks-$i-$commit_hash - # flamegraph $i -done - -echo -e "\033[Building for latest...\033[0m" -sed -i.bak "s/^automata = { .* }$/automata = { path=\"..\/automata\" }/" $CARGO_TOML -build_binary 3 "latest" -cp ./bench/target/release/automata-benchmarks ./bench/built-automata-benchmarks-latest - -hyperfine --warmup 5 --ignore-failure --runs 20 ./bench/built-automata-benchmarks-* --export-csv benchmarks.csv - From c2569fe19d1c43e6af2e88d58d60443890746b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Bohn?= Date: Fri, 31 Oct 2025 12:10:27 +0100 Subject: [PATCH 2/2] Little python work --- Cargo.toml | 6 ++--- python/Cargo.toml | 4 ++-- python/src/dpa.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++ python/src/lib.rs | 17 ++++++++------ 4 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 python/src/dpa.rs diff --git a/Cargo.toml b/Cargo.toml index 70255a0..f2bbc86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,9 +2,9 @@ # we use the 2024 edition resolver resolver = "3" -members = ["crates/*", "bin/*"] -default-members = ["crates/automata", "crates/automata-*", "crates/hoars", "bin/*"] -exclude = ["python", "bench"] +members = ["crates/*", "bin/*", "python"] +default-members = ["crates/automata", "crates/automata-*", "crates/hoars", "python", "bin/*"] +exclude = [] [workspace.dependencies] tracing = "0.1" diff --git a/python/Cargo.toml b/python/Cargo.toml index 23b6a83..fac01a2 100644 --- a/python/Cargo.toml +++ b/python/Cargo.toml @@ -9,5 +9,5 @@ name = "automata" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.21.1" -automata = { path = "../" } +pyo3 = "0.27" +automata = { path = "../crates/automata" } diff --git a/python/src/dpa.rs b/python/src/dpa.rs new file mode 100644 index 0000000..9f43ccd --- /dev/null +++ b/python/src/dpa.rs @@ -0,0 +1,59 @@ +use automata::{ + TransitionSystem, + automaton::DPA, + core::{Void, alphabet::CharAlphabet}, + ts::{Shrinkable, Sproutable}, +}; +use pyo3::prelude::*; + +#[pyclass(name = "DPA")] +pub struct PyDPA { + inner: DPA, +} + +#[pymethods] +impl PyDPA { + #[new] + #[pyo3(signature = (alphabet_size))] + pub fn new(alphabet_size: u8) -> Self { + Self { + inner: DPA::new_with_initial_color(CharAlphabet::of_size(alphabet_size as usize), Void), + } + } + + pub fn size(&self) -> usize { + self.inner.size() + } + + pub fn add_state(&mut self) -> u32 { + self.inner.add_state(Void) + } + + /// Removes state with given id, returns `true` if some state is removed and `false` if no state was removed. + pub fn remove_state(&mut self, id: u32) -> bool { + self.inner.remove_state(id).is_some() + } + + pub fn add_edge( + &mut self, + source: u32, + symbol: char, + priority: u8, + target: u32, + ) -> Option { + self.inner + .add_edge((source, symbol, priority, target)) + .map(|tup| tup.3) + } + + pub fn remove_edge(&mut self, source: u32, symbol: char, target: u32) -> bool { + let Some(removed) = self + .inner + .remove_edges_between_matching(source, target, symbol) + else { + return false; + }; + assert!(removed.len() <= 1); + removed.is_empty() + } +} diff --git a/python/src/lib.rs b/python/src/lib.rs index 4db2f33..2a8728e 100644 --- a/python/src/lib.rs +++ b/python/src/lib.rs @@ -1,5 +1,14 @@ +use ::automata::{ + TransitionSystem, + automaton::DFA, + core::alphabet::CharAlphabet, + ts::{Shrinkable, Sproutable}, +}; use pyo3::prelude::*; +mod dpa; +pub use dpa::*; + #[pyclass(name = "DFA")] pub struct PyDFA { inner: DFA, @@ -58,16 +67,10 @@ impl PyDFA { } } -/// Formats the sum of two numbers as string. -#[pyfunction] -fn sum_as_string(a: usize, b: usize) -> PyResult { - Ok((a + b).to_string()) -} - /// A Python module implemented in Rust. #[pymodule] fn automata(m: &Bound<'_, PyModule>) -> PyResult<()> { - m.add_function(wrap_pyfunction!(sum_as_string, m)?)?; m.add_class::()?; + m.add_class::()?; Ok(()) }