diff --git a/Cargo.lock b/Cargo.lock index 2eb2eb5..4fc78cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,17 +31,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "getrandom" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "heck" version = "0.4.1" @@ -85,17 +74,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "lyagushka" -version = "0.1.0" -dependencies = [ - "atty", - "pyo3", - "rand", - "serde", - "serde_json", -] - [[package]] name = "memoffset" version = "0.9.0" @@ -134,12 +112,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - [[package]] name = "proc-macro2" version = "1.0.78" @@ -149,6 +121,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pyagushka" +version = "0.1.0" +dependencies = [ + "atty", + "pyo3", + "serde", + "serde_json", +] + [[package]] name = "pyo3" version = "0.20.2" @@ -219,36 +201,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -336,12 +288,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 0a937b1..b875495 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,15 +1,18 @@ [package] -name = "lyagushka" +name = "pyagushka" version = "0.1.0" edition = "2021" [lib] -name = "lyagushka" +name = "pyagushka" crate-type = ["cdylib"] [dependencies] atty = "0.2.14" pyo3 = "0.20.2" -rand = "0.8.5" serde = { version = "1.0.196", features = ["derive"] } serde_json = "1.0.113" + +[features] +extension-module = ["pyo3/extension-module"] +default = ["extension-module"] \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..31e63bc --- /dev/null +++ b/readme.md @@ -0,0 +1,61 @@ +# lyagushka + +(Russian лягушка: frog) + +Cluster and Gap Analysis Tool inspired by Fatum Project's 'Zhaba' algorithm (Russian 'жаба': toad) that finds attractor clusters in lists of integers. + +This Rust command-line tool analyzes a dataset of integers to identify clusters of closely grouped points and significant gaps between these clusters. It calculates z-scores for each cluster or gap to measure their statistical significance relative to the dataset's mean distance. The analysis results, including clusters, gaps, and their z-scores, are output as a JSON string. + +## Features + +- **Cluster Identification**: Identifies groups of points that are closely spaced together based on a customizable threshold. +- **Gap Detection**: Detects significant gaps between clusters, providing insights into the dataset's distribution. +- **Z-Score Calculation**: Calculates z-scores for both clusters and gaps, offering a statistical measure of their deviation from the mean distance. +- **Flexible Input**: Accepts input data either from a file specified as a command-line argument or piped directly into stdin. +- **JSON Output**: Outputs the analysis results in a readable JSON format, making it easy to interpret or use in further processing. + +## Usage + +### From a File + +To analyze a dataset from a file, provide the filename as an argument along with two additional parameters: the factor for adjusting clustering and gap detection thresholds, and the minimum cluster size. + +```sh +cargo run -- filename.txt 0.5 2 +``` + +### From Stdin + +Alternatively, you can pipe a list of integers into the tool, followed by the factor and minimum cluster size. + +```sh +echo "1\n2\n10\n20" | cargo run -- 0.5 2 +``` + +#### Parameters + +* `filename.txt` (optional): A file containing a newline-separated list of integers to analyze. If not provided, the program expects input from stdin. +* `factor`: A floating-point value used to fine-tune the sensitivity of cluster and gap detection. Lower values result in tighter clusters and wider gaps, while higher values do the opposite. +* `min_cluster_size`: An integer specifying the minimum number of contiguous points required to be considered a cluster. + +### Output + +The tool outputs a JSON string that includes details about the identified clusters and gaps, along with their respective z-scores. Here's an example of the JSON output format: + +```json + +[ + { + "span_length": 1.0, + "num_elements": 2, + "centroid": 1.5, + "z_score": -1.23 + }, + { + "span_length": 8.0, + "num_elements": 0, + "centroid": 6.0, + "z_score": 2.45 + } +] +``` \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 9e1d814..be7ce3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -167,7 +167,7 @@ fn lyagushka(_py: Python, int_list: &PyList, factor: f32, min_cluster_size: usiz #[pymodule] -fn lyagushka_module(_py: Python, m: &PyModule) -> PyResult<()> { +fn pyagushka(_py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(lyagushka, m)?)?; Ok(()) } diff --git a/test.py b/test.py new file mode 100644 index 0000000..91531d2 --- /dev/null +++ b/test.py @@ -0,0 +1,13 @@ +from pyagushka import lyagushka +from randonautentropy import rndo +import json + +random_data = [] + +with open('random_values.txt', 'r') as file: + for line in file: + random_data.append(int(line.strip())) + +anomalies = json.loads(lyagushka(random_data, 1.0, 5)) + +print(anomalies) \ No newline at end of file