use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub mod streaming_alpha;
pub mod streaming_astar;
pub mod streaming_declare;
pub mod streaming_dfg;
pub mod streaming_heuristic;
pub mod streaming_hill_climbing;
pub mod streaming_hybrid;
pub mod streaming_inductive;
pub mod streaming_noise_filtered_dfg;
pub mod streaming_skeleton;
pub use streaming_dfg::StreamingDfgBuilder;
pub use streaming_heuristic::StreamingHeuristicBuilder;
pub use streaming_skeleton::StreamingSkeletonBuilder;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StreamStats {
pub event_count: usize,
pub trace_count: usize,
pub open_traces: usize,
pub memory_bytes: usize,
pub activities: usize,
}
pub trait StreamingAlgorithm {
type Model;
fn new() -> Self;
fn add_event(&mut self, case_id: &str, activity: &str);
fn add_batch(&mut self, events: &[(String, String)]) {
for (case_id, activity) in events {
self.add_event(case_id, activity);
}
}
fn close_trace(&mut self, case_id: &str) -> bool;
fn snapshot(&self) -> Self::Model;
fn finalize(mut self) -> Self::Model
where
Self: Sized,
{
let case_ids: Vec<String> = self.open_trace_ids();
for case_id in case_ids {
self.close_trace(&case_id);
}
self.snapshot()
}
fn stats(&self) -> StreamStats;
fn open_trace_ids(&self) -> Vec<String> {
Vec::new() }
}
pub trait ActivityInterner {
fn intern(&mut self, activity: &str) -> u32;
fn lookup(&self, id: u32) -> Option<&str>;
fn vocab_size(&self) -> usize;
}
#[derive(Debug, Clone)]
pub struct Interner {
vocab_map: HashMap<String, u32>,
vocab: Vec<String>,
}
impl Interner {
pub fn new() -> Self {
Interner {
vocab_map: HashMap::new(),
vocab: Vec::new(),
}
}
pub fn len(&self) -> usize {
self.vocab.len()
}
pub fn is_empty(&self) -> bool {
self.vocab.is_empty()
}
pub fn get(&self, id: u32) -> Option<&str> {
self.vocab.get(id as usize).map(|s| s.as_str())
}
pub fn vocab(&self) -> &[String] {
&self.vocab
}
}
impl ActivityInterner for Interner {
#[inline]
fn intern(&mut self, activity: &str) -> u32 {
if let Some(&id) = self.vocab_map.get(activity) {
return id;
}
let id = self.vocab.len() as u32;
self.vocab.push(activity.to_owned());
self.vocab_map.insert(activity.to_owned(), id);
id
}
#[inline]
fn lookup(&self, id: u32) -> Option<&str> {
self.get(id)
}
#[inline]
fn vocab_size(&self) -> usize {
self.len()
}
}
impl Default for Interner {
fn default() -> Self {
Self::new()
}
}
macro_rules! impl_activity_interner {
($struct_name:ident) => {
impl crate::streaming::ActivityInterner for $struct_name {
#[inline]
fn intern(&mut self, activity: &str) -> u32 {
if let Some(&id) = self.interner.vocab_map.get(activity) {
return id;
}
let id = self.interner.vocab.len() as u32;
self.interner.vocab.push(activity.to_owned());
self.interner.vocab_map.insert(activity.to_owned(), id);
id
}
#[inline]
fn lookup(&self, id: u32) -> Option<&str> {
self.interner.get(id)
}
#[inline]
fn vocab_size(&self) -> usize {
self.interner.len()
}
}
};
}
#[allow(unused_macros)]
macro_rules! impl_activity_interner_methods {
($struct_name:ident) => {
impl $struct_name {
#[inline]
pub fn intern(&mut self, activity: &str) -> u32 {
if let Some(&id) = self.interner.vocab_map.get(activity) {
return id;
}
let id = self.interner.vocab.len() as u32;
self.interner.vocab.push(activity.to_owned());
self.interner.vocab_map.insert(activity.to_owned(), id);
id
}
#[inline]
pub fn lookup(&self, id: u32) -> Option<&str> {
self.interner.get(id)
}
#[inline]
pub fn vocab_size(&self) -> usize {
self.interner.len()
}
}
};
}
pub(crate) use impl_activity_interner;
#[allow(unused_imports)]
pub(crate) use impl_activity_interner_methods;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_interner_basic() {
let mut interner = Interner::new();
let id_a = interner.intern("A");
assert_eq!(id_a, 0);
assert_eq!(interner.len(), 1);
let id_a2 = interner.intern("A");
assert_eq!(id_a2, 0);
assert_eq!(interner.len(), 1);
let id_b = interner.intern("B");
assert_eq!(id_b, 1);
assert_eq!(interner.len(), 2);
assert_eq!(interner.get(0), Some("A"));
assert_eq!(interner.get(1), Some("B"));
assert_eq!(interner.get(2), None);
}
#[test]
fn test_stream_stats_default() {
let stats = StreamStats {
event_count: 0,
trace_count: 0,
open_traces: 0,
memory_bytes: 0,
activities: 0,
};
assert_eq!(stats.event_count, 0);
assert_eq!(stats.trace_count, 0);
assert_eq!(stats.open_traces, 0);
}
}