| Crates.io | rust-rule-miner |
| lib.rs | rust-rule-miner |
| version | 0.2.2 |
| created_at | 2026-01-03 15:20:51.295828+00 |
| updated_at | 2026-01-06 09:08:45.945438+00 |
| description | Automatic rule discovery from historical data using association rule mining, sequential pattern mining, and graph-based pattern matching. Generates and executes rules with rust-rule-engine integration. |
| homepage | |
| repository | https://github.com/KSD-CO/rust-rule-miner |
| max_upload_size | |
| id | 2020316 |
| size | 457,279 |
Automatic rule discovery from historical data using association rule mining, sequential pattern mining, and graph-based pattern matching.
Discover business rules, recommendations, and patterns from your data without manual rule authoring!
postgres feature) - Stream and mine data directly from PostgreSQLcloud feature) - Load data from AWS S3 and HTTP endpointsuse rust_rule_miner::{RuleMiner, Transaction, MiningConfig, MiningAlgorithm};
use chrono::Utc;
// 1. Create transactions with items you want to mine patterns from
// Each transaction contains: ID, items (the values to find patterns in), timestamp
let transactions = vec![
Transaction::new("tx1", vec!["Laptop".to_string(), "Mouse".to_string(), "Keyboard".to_string()], Utc::now()),
Transaction::new("tx2", vec!["Laptop".to_string(), "Mouse".to_string()], Utc::now()),
Transaction::new("tx3", vec!["Laptop".to_string(), "Mouse".to_string(), "USB-C Hub".to_string()], Utc::now()),
Transaction::new("tx4", vec!["Phone".to_string(), "Phone Case".to_string()], Utc::now()),
];
// The miner will find patterns like: "Laptop" often appears with "Mouse"
// 2. Configure mining parameters
let config = MiningConfig {
min_support: 0.3, // 30% of transactions
min_confidence: 0.7, // 70% confidence
min_lift: 1.2, // 20% above random chance
max_time_gap: None,
algorithm: MiningAlgorithm::Apriori,
};
// 3. Mine association rules
let mut miner = RuleMiner::new(config);
miner.add_transactions(transactions)?;
let rules = miner.mine_association_rules()?;
// 4. Display discovered rules
for rule in &rules {
println!("Rule: {:?} => {:?}", rule.antecedent, rule.consequent);
println!(" Confidence: {:.1}%", rule.metrics.confidence * 100.0);
println!(" Support: {:.1}%", rule.metrics.support * 100.0);
println!(" Lift: {:.2}", rule.metrics.lift);
}
// Output:
// Rule: ["Laptop"] => ["Mouse"]
// Confidence: 100.0%
// Support: 75.0%
// Lift: 1.33
Default installation (includes rust-rule-engine for execution):
[dependencies]
rust-rule-miner = "0.2.2"
Mining-only (without engine, just export to GRL):
[dependencies]
rust-rule-miner = { version = "0.2.2", default-features = false }
With additional features:
[dependencies]
# Add PostgreSQL streaming support
rust-rule-miner = { version = "0.2.2", features = ["postgres"] }
# Add cloud storage support (S3, HTTP)
rust-rule-miner = { version = "0.2.2", features = ["cloud"] }
# Combine all features
rust-rule-miner = { version = "0.2.2", features = ["postgres", "cloud"] }
# Mining-only + PostgreSQL (without engine)
rust-rule-miner = { version = "0.2.2", default-features = false, features = ["postgres"] }
Stream large datasets with constant memory usage using excelstream:
use rust_rule_miner::data_loader::{DataLoader, ColumnMapping};
// Specify which columns to mine: transaction_id, items, timestamp
let mapping = ColumnMapping::simple(0, 1, 2);
// Load from CSV file (ultra-fast, ~1.2M rows/sec)
let transactions = DataLoader::from_csv("sales_data.csv", mapping.clone())?;
// Load from Excel file (.xlsx)
let transactions = DataLoader::from_excel("sales_data.xlsx", 0, mapping)?; // 0 = first sheet
// Mine rules from loaded data
let mut miner = RuleMiner::new(config);
miner.add_transactions(transactions)?;
let rules = miner.mine_association_rules()?;
Memory usage: ~3-35 MB regardless of file size! π
No preprocessing needed! Use ColumnMapping to mine any fields directly:
ColumnMapping API:
// Single field mining
ColumnMapping::simple(
transaction_id_column: usize, // Column index for transaction/group ID
item_column: usize, // Column index for items to mine
timestamp_column: usize // Column index for timestamp
)
// Multi-field mining (combine multiple columns)
ColumnMapping::multi_field(
transaction_id_column: usize, // Column index for transaction/group ID
item_columns: Vec<usize>, // Column indices to combine
timestamp_column: usize, // Column index for timestamp
field_separator: String // Separator for combined fields (e.g., "::")
)
Examples:
use rust_rule_miner::data_loader::{DataLoader, ColumnMapping};
// CSV: customer_id, product_name, category, price, location, timestamp
// 0 1 2 3 4 5
// Option 1: Mine product names (column 1)
let mapping = ColumnMapping::simple(0, 1, 5); // tx_id=0, items=1, timestamp=5
let transactions = DataLoader::from_csv("sales.csv", mapping)?;
// Option 2: Mine categories (column 2)
let mapping = ColumnMapping::simple(0, 2, 5); // tx_id=0, items=2, timestamp=5
let transactions = DataLoader::from_csv("sales.csv", mapping)?;
// Option 3: Mine product + category combined
let mapping = ColumnMapping::multi_field(
0, // transaction_id column
vec![1, 2], // product(1) + category(2)
5, // timestamp column
"::".to_string() // separator
);
let transactions = DataLoader::from_csv("sales.csv", mapping)?;
// Items: "Laptop::Electronics", "Mouse::Accessories"
// Option 4: Mine product + category + location
let mapping = ColumnMapping::multi_field(0, vec![1, 2, 4], 5, "::".to_string());
let transactions = DataLoader::from_csv("sales.csv", mapping)?;
// Items: "Laptop::Electronics::US", "Mouse::Accessories::UK"
Multi-field zipping: If your CSV has comma-separated values in multiple columns:
customer_id,products,categories,locations,timestamp
123,"Laptop,Mouse","Electronics,Accessories","US,US",2024-01-01
The miner will automatically zip them together:
let mapping = ColumnMapping::multi_field(0, vec![1, 2, 3], 4, "::".to_string());
// Result: ["Laptop::Electronics::US", "Mouse::Accessories::US"]
use rust_rule_miner::{RuleMiner, MiningConfig, data_loader::{DataLoader, ColumnMapping}};
// Load historical purchase data from CSV (transaction_id, items, timestamp)
let mapping = ColumnMapping::simple(0, 1, 2);
let transactions = DataLoader::from_csv("purchase_history.csv", mapping)?;
// Configure mining parameters
let config = MiningConfig {
min_support: 0.05,
min_confidence: 0.6,
..Default::default()
};
// Discover: "Customers who bought X also bought Y"
let mut miner = RuleMiner::new(config);
miner.add_transactions(transactions)?;
let rules = miner.mine_association_rules()?;
// Result: Laptop (85%) β Mouse, Keyboard (75%) β Monitor
use rust_rule_miner::{RuleMiner, MiningConfig};
// Configure for fraud detection
let config = MiningConfig {
min_support: 0.02, // Even rare patterns matter
min_confidence: 0.85, // High confidence required
..Default::default()
};
// Find patterns unique to fraud cases
let mut fraud_miner = RuleMiner::new(config);
fraud_miner.add_transactions(fraud_cases)?;
let patterns = fraud_miner.mine_association_rules()?;
// Result: IP_mismatch + unusual_time + high_amount β fraud (90%)
// Discover: "Symptoms A, B, C β Likely Disease X"
let medical_miner = RuleMiner::new(MiningConfig {
min_confidence: 0.90, // High confidence for medical
..Default::default()
});
use rust_rule_miner::{RuleMiner, MiningConfig};
use std::time::Duration;
// Find time-ordered patterns
let config = MiningConfig {
max_time_gap: Some(Duration::from_secs(7 * 24 * 3600)), // 7 days
..Default::default()
};
let mut miner = RuleMiner::new(config);
miner.add_transactions(transactions)?;
let sequential_patterns = miner.find_sequential_patterns()?;
// Result: Laptop β (2 days) β Mouse β (5 days) β Laptop Bag
Execute mined rules in real-time with built-in rust-rule-engine support (included by default).
Two-Phase Approach:
use rust_rule_miner::{RuleMiner, MiningConfig, data_loader::{DataLoader, ColumnMapping}};
use rust_rule_miner::engine::{MiningRuleEngine, facts_from_cart};
// Load historical data (transaction_id, items, timestamp)
let mapping = ColumnMapping::simple(0, 1, 2);
let transactions = DataLoader::from_csv("sales_history.csv", mapping)?;
// PHASE 1: Mine rules with quality criteria
let config = MiningConfig {
min_support: 0.3, // Pattern must appear in 30%+ of transactions
min_confidence: 0.7, // Rule must be correct 70%+ of the time
min_lift: 1.2, // Rule must be 20%+ better than random
..Default::default()
};
let mut miner = RuleMiner::new(config);
miner.add_transactions(transactions)?;
let rules = miner.mine_association_rules()?; // β Only high-quality rules
// PHASE 2: Load filtered rules into engine and execute
let mut engine = MiningRuleEngine::new("ProductRecommendations");
engine.load_rules(&rules)?; // β Loads only the filtered rules from Phase 1
// Execute in real-time
let facts = facts_from_cart(vec!["Laptop".to_string()]);
let result = engine.execute(&facts)?;
if let Some(recommendations) = result.get("Recommendation.items") {
println!("Recommend: {:?}", recommendations); // ["Mouse", "Keyboard"]
}
Key Point: Mining criteria are applied during mine_association_rules(), not during execution. The engine only executes pre-filtered high-quality rules.
No more hardcoded field names! Configure for any use case:
use rust_rule_miner::export::{GrlConfig, GrlExporter};
// E-commerce
let ecommerce_config = GrlConfig::custom("Cart.items", "Recommendations.products");
let grl = GrlExporter::to_grl_with_config(&rules, &ecommerce_config);
// Fraud detection
let fraud_config = GrlConfig::custom("Transaction.indicators", "FraudAlert.flags");
let grl = GrlExporter::to_grl_with_config(&rules, &fraud_config);
// Security
let security_config = GrlConfig::custom("NetworkActivity.events", "SecurityAlert.threats");
let grl = GrlExporter::to_grl_with_config(&rules, &security_config);
See examples/flexible_domain_mining.rs for complete examples across multiple domains.
Generated GRL (rust-rule-engine v1.15.0+ with += operator):
// Auto-generated rules from pattern mining
// Generated: 2026-01-03 14:00:00 UTC
// Rule #1: Laptop β Mouse
// Confidence: 85.7% | Support: 60.0% | Lift: 1.43
rule "Mined_Laptop_Implies_Mouse" salience 85 no-loop {
when
ShoppingCart.items contains "Laptop" &&
!(Recommendation.items contains "Mouse")
then
Recommendation.items += "Mouse"; // Array append operator (v1.15.0+)
LogMessage("Rule fired: confidence 85.7%");
}
Each discovered rule includes:
Benchmarks with default config (min_support=0.05, min_confidence=0.6):
| Dataset Size | Algorithm | Time | Memory | Throughput |
|---|---|---|---|---|
| 100 transactions | Apriori | ~10-20ms | ~5 MB | 5-10K tx/s |
| 1,000 transactions | Apriori | ~100-200ms | ~10-15 MB | 5-10K tx/s |
| 10,000 transactions | Apriori | ~1-2s | ~30-50 MB | 5-10K tx/s |
| 100,000 transactions | Apriori | ~10-20s | ~200-500 MB | 5-10K tx/s |
Notes:
This crate is designed to work seamlessly with rust-rule-engine v1.15.0+:
+= array append operatorRequirements: rust-rule-engine v1.15.0 or higher (for += operator support)
[dev-dependencies]
rust-rule-engine = "1.15.0" # Required for += array append in GRL
See examples/ directory:
Basic Examples:
01_simple_ecommerce.rs - Simple e-commerce with engine execution02_medium_complexity.rs - Medium complexity patterns with RETE03_advanced_large_dataset.rs - Large-scale mining with statistics04_load_from_excel_csv.rs - Loading data from Excel/CSV with ColumnMappingbasic_mining.rs - Basic association rule miningEngine Integration:
integration_with_engine.rs - Simple MiningRuleEngine APIintegration_with_rete.rs - High-performance RETE engineflexible_domain_mining.rs - Multi-domain examples (fraud, security, content)Advanced Features:
postgres_stream_mining.rs - PostgreSQL streaming + mining (requires postgres feature)performance_test.rs - Performance benchmarkingcloud_demo.rs - Cloud storage integration (requires cloud feature)excelstream_demo.rs - Excel streaming examplesCompleted (v0.2.0):
Planned:
Getting Started:
v0.2.0 Engine Integration:
Advanced Topics:
Contributions welcome! See CONTRIBUTING.md.
MIT License - see LICENSE file.
Built with β€οΈ in Rust π¦