use crate::{
ebi_framework::{
ebi_command::EbiCommand,
ebi_input::{EbiInput, EbiInputType},
ebi_output::{EbiOutput, EbiOutputType},
ebi_trait::EbiTrait,
ebi_trait_object::EbiTraitObject,
},
ebi_traits::{
ebi_trait_finite_language::EbiTraitFiniteLanguage,
ebi_trait_finite_stochastic_language::EbiTraitFiniteStochasticLanguage,
},
techniques::{
flower_miner::{FlowerMinerDFA, FlowerMinerTree},
inductive_miner::{InductiveMiner, InductiveMinerInfrequent},
prefix_tree_miner::{PrefixTreeMinerDFA, PrefixTreeMinerTree},
trace_model_miner::TraceModelMinerTree,
},
};
use ebi_objects::{
EbiObject, EbiObjectType, HasActivityKey,
anyhow::{Context, anyhow},
ebi_arithmetic::{ConstFraction, Fraction},
};
pub const EBI_DISCOVER_NON_STOCHASTIC: EbiCommand = EbiCommand::Group {
name_short: "dins",
name_long: Some("discover-non-stochastic"),
explanation_short: "Discover a non-stochastic process model.",
explanation_long: None,
children: &[
&EBI_DISCOVER_NON_STOCHASTIC_FLOWER,
&EBI_DISCOVER_NON_STOCHASTIC_PREFIX,
&EBI_DISCOVER_NON_STOCHASTIC_TRACE_MODEL,
&EBI_DISCOVER_NON_STOCHASTIC_INDUCTIVE_MINER,
&EBI_DISCOVER_NON_STOCHASTIC_INDUCTIVE_MINER_INFREQUENT,
],
};
pub const EBI_DISCOVER_NON_STOCHASTIC_FLOWER: EbiCommand = EbiCommand::Group {
name_short: "flw",
name_long: Some("flower"),
explanation_short: "Discover a model that supports any trace with the activities of the log or model.",
explanation_long: None,
children: &[
&EBI_DISCOVER_NON_STOCHASTIC_FLOWER_DFA,
&EBI_DISCOVER_NON_STOCHASTIC_FLOWER_TREE,
],
};
pub const EBI_DISCOVER_NON_STOCHASTIC_FLOWER_DFA: EbiCommand = EbiCommand::Command {
name_short: "dfa",
name_long: Some("deterministic-finite-automaton"),
explanation_short: "Discover a DFA that supports any trace with the activities of the log.",
explanation_long: None,
latex_link: None,
cli_command: None,
exact_arithmetic: true,
input_types: &[&[
&EbiInputType::Trait(EbiTrait::FiniteLanguage),
&EbiInputType::Trait(EbiTrait::Activities),
]],
input_names: &["FILE"],
input_helps: &["A file with activities."],
execute: |mut inputs, _| {
Ok(EbiOutput::Object(EbiObject::DeterministicFiniteAutomaton(
match inputs.remove(0) {
EbiInput::Trait(EbiTraitObject::FiniteLanguage(lang), _) => {
let lang: Box<dyn HasActivityKey> = lang;
lang.mine_flower_dfa()
.with_context(|| format!("cannot compute flower model"))?
}
EbiInput::Trait(EbiTraitObject::Activities(lang), _) => {
let lang: Box<dyn HasActivityKey> = lang;
lang.mine_flower_dfa()
.with_context(|| format!("cannot compute flower model"))?
}
object => {
return Err(anyhow!(
"Unsupported object {:?} provided.",
object.get_type()
));
}
},
)))
},
output_type: &EbiOutputType::ObjectType(EbiObjectType::DeterministicFiniteAutomaton),
};
pub const EBI_DISCOVER_NON_STOCHASTIC_FLOWER_TREE: EbiCommand = EbiCommand::Command {
name_short: "ptree",
name_long: Some("process-tree"),
explanation_short: "Discover a process tree that supports any trace with the activities of the log.",
explanation_long: None,
latex_link: None,
cli_command: None,
exact_arithmetic: true,
input_types: &[&[
&EbiInputType::Trait(EbiTrait::FiniteLanguage),
&EbiInputType::Trait(EbiTrait::Activities),
]],
input_names: &["FILE"],
input_helps: &["A file with activities."],
execute: |mut inputs, _| {
Ok(EbiOutput::Object(EbiObject::ProcessTree(
match inputs.remove(0) {
EbiInput::Trait(EbiTraitObject::FiniteLanguage(lang), _) => lang.mine_flower_tree(),
EbiInput::Trait(EbiTraitObject::Activities(lang), _) => {
let lang: Box<dyn HasActivityKey> = lang;
lang.mine_flower_tree()
}
object => {
return Err(anyhow!(
"Unsupported object {:?} provided.",
object.get_type()
));
}
},
)))
},
output_type: &EbiOutputType::ObjectType(EbiObjectType::ProcessTree),
};
pub const EBI_DISCOVER_NON_STOCHASTIC_PREFIX: EbiCommand = EbiCommand::Group {
name_short: "pfxt",
name_long: Some("prefix-tree"),
explanation_short: "Discover a prefix tree model of the log.",
explanation_long: None,
children: &[
&EBI_DISCOVER_NON_STOCHASTIC_TREE_DFA,
&EBI_DISCOVER_NON_STOCHASTIC_TREE_TREE,
],
};
pub const EBI_DISCOVER_NON_STOCHASTIC_TREE_DFA: EbiCommand = EbiCommand::Command {
name_short: "dfa",
name_long: Some("deterministic-finite-automaton"),
explanation_short: "Discover a DFA that is a prefix tree of the log.",
explanation_long: None,
latex_link: None,
cli_command: None,
exact_arithmetic: true,
input_types: &[&[&EbiInputType::Trait(EbiTrait::FiniteLanguage)]],
input_names: &["LANG"],
input_helps: &["A finite language."],
execute: |mut inputs, _| {
let lpn = inputs.remove(0).to_type::<dyn EbiTraitFiniteLanguage>()?;
Ok(EbiOutput::Object(EbiObject::DeterministicFiniteAutomaton(
lpn.mine_prefix_tree_dfa(),
)))
},
output_type: &EbiOutputType::ObjectType(EbiObjectType::DeterministicFiniteAutomaton),
};
pub const EBI_DISCOVER_NON_STOCHASTIC_TREE_TREE: EbiCommand = EbiCommand::Command {
name_short: "ptree",
name_long: Some("process-tree"),
explanation_short: "Discover a process tree that is a prefix tree of the log.",
explanation_long: None,
latex_link: None,
cli_command: None,
exact_arithmetic: true,
input_types: &[&[&EbiInputType::Trait(EbiTrait::FiniteLanguage)]],
input_names: &["LANG"],
input_helps: &["A finite language."],
execute: |mut inputs, _| {
let lpn = inputs.remove(0).to_type::<dyn EbiTraitFiniteLanguage>()?;
Ok(EbiOutput::Object(EbiObject::ProcessTree(
lpn.mine_prefix_tree_tree(),
)))
},
output_type: &EbiOutputType::ObjectType(EbiObjectType::ProcessTree),
};
pub const EBI_DISCOVER_NON_STOCHASTIC_TRACE_MODEL: EbiCommand = EbiCommand::Command {
name_short: "tm",
name_long: Some("trace-model"),
explanation_short: "Discover a model that is a choice between all traces of the model.",
explanation_long: None,
latex_link: None,
cli_command: None,
exact_arithmetic: true,
input_types: &[&[&EbiInputType::Trait(EbiTrait::FiniteLanguage)]],
input_names: &["LANG"],
input_helps: &["A finite language."],
execute: |mut inputs, _| {
let lpn = inputs.remove(0).to_type::<dyn EbiTraitFiniteLanguage>()?;
Ok(EbiOutput::Object(EbiObject::ProcessTree(
lpn.mine_trace_model_tree(),
)))
},
output_type: &EbiOutputType::ObjectType(EbiObjectType::ProcessTree),
};
pub const EBI_DISCOVER_NON_STOCHASTIC_INDUCTIVE_MINER: EbiCommand = EbiCommand::Command {
name_short: "im",
name_long: Some("inductive-miner"),
explanation_short: "Discover a process tree using the Inductive Miner algorithm.",
explanation_long: Some("Discover a process tree using the Inductive Miner.
Please note that this implementation closely follows the thesis version; it is not equivalent to the ProM implementation."),
latex_link: Some("\\cite{DBLP:series/lnbip/Leemans22}"),
cli_command: None,
exact_arithmetic: true,
input_types: &[
&[&EbiInputType::Trait(EbiTrait::FiniteLanguage)],
],
input_names: &["LANG"],
input_helps: &[
"A finite language."
],
execute: |mut inputs, _| {
let lang = inputs.remove(0).to_type::<dyn EbiTraitFiniteLanguage>()?;
Ok(EbiOutput::Object(EbiObject::ProcessTree(
lang.inductive_miner(),
)))
},
output_type: &EbiOutputType::ObjectType(EbiObjectType::ProcessTree),
};
pub const EBI_DISCOVER_NON_STOCHASTIC_INDUCTIVE_MINER_INFREQUENT: EbiCommand = EbiCommand::Command {
name_short: "imf",
name_long: Some("inductive-miner-infrequent"),
explanation_short: "Discover a process tree using the Inductive Miner-infrequent algorithm.",
explanation_long: Some("Discover a process tree using the Inductive Miner-infrequent algorithm.
If the given noise parameter is 0, then behaves as the Inductive Miner algorithm.
Please note that this implementation closely follows the thesis version; it is not equivalent to the ProM implementation."),
latex_link: Some("\\cite{DBLP:series/lnbip/Leemans22}"),
cli_command: None,
exact_arithmetic: true,
input_types: &[
&[&EbiInputType::Trait(EbiTrait::FiniteStochasticLanguage)],
&[&EbiInputType::Fraction(
Some(ConstFraction::zero()),
Some(ConstFraction::one()),
Some(ConstFraction::of(2, 10)),
)],
],
input_names: &["SLANG", "NOISE"],
input_helps: &[
"A finite stochastic language.",
"The amount of noise filtering, where 0 means no noise filtering is applied, and 1 means that maximum noise filtering is applied.",
],
execute: |mut inputs, _| {
let slang = inputs.remove(0).to_type::<dyn EbiTraitFiniteStochasticLanguage>()?;
let noise = inputs.remove(0).to_type::<Fraction>()?;
Ok(EbiOutput::Object(EbiObject::ProcessTree(
slang.inductive_miner_infrequent(&noise),
)))
},
output_type: &EbiOutputType::ObjectType(EbiObjectType::ProcessTree),
};