use std::collections::{HashSet, VecDeque};
use crate::arbitrary::NonDeterministicAutomaton;
use crate::finite::automaton::FiniteAutomaton;
use crate::labeled::finite::DeterministicFiniteLabeledAutomaton;
use crate::labeled::finite::NonDeterministicFiniteLabeledAutomaton;
use crate::utility::clone_reduce;
pub trait NonDeterministicFiniteAutomaton:
NonDeterministicAutomaton + FiniteAutomaton + NonDeterministicFiniteLabeledAutomaton<()>
{
fn difference(&self, other: &Self) -> Self;
fn concatenate(&self, other: &Self) -> Self;
fn intersection(&self, other: &Self) -> Self;
fn star(&self) -> Self;
fn reverse(&self) -> Self;
fn trimmed(&self) -> Self;
fn complement(&self) -> Self;
fn accessible(&self) -> Self;
fn co_accessible(&self) -> Self;
fn to_dfa(&self) -> Self::CorrespondingDFA {
self.to_dfa_by(|_, _| ())
}
fn to_minimized_dfa(&self) -> Self::CorrespondingDFA {
self.to_dfa().minimize()
}
fn concatenate_all(automata: &[Self]) -> Option<Self>
where
Self: Clone,
{
clone_reduce(automata, |a, b| a.concatenate(b))
}
fn intersect_all(automata: &[Self]) -> Option<Self>
where
Self: Clone,
{
clone_reduce(automata, |a, b| a.intersection(b))
}
fn accepting_states_compatible_with(&self, other: &Self) -> HashSet<Self::State> {
let mut common = HashSet::new();
let mut queue = VecDeque::new();
let mut visited = HashSet::new();
let common_alphabet = self.common_alphabet(other);
for initial_state1 in self.initial_states() {
for initial_state2 in other.initial_states() {
queue.push_back((initial_state1, initial_state2));
}
}
while let Some((state1, state2)) = queue.pop_front() {
if visited.contains(&(state1, state2)) {
continue;
}
visited.insert((state1, state2));
if self.is_accepting_state(state1) && other.is_accepting_state(state2) {
common.insert(state1);
}
for input in &common_alphabet {
for new_state1 in self.successors(state1, input) {
for new_state2 in other.successors(state2, input) {
queue.push_back((new_state1, new_state2));
}
}
}
}
common
}
fn is_empty_language(&self) -> bool {
!self
.reachable_states_set()
.iter()
.any(|&s| self.is_accepting_state(s))
}
fn is_subset_of(&self, other: &Self) -> bool {
self.difference(other).is_empty_language()
}
fn is_equivalent_to(&self, other: &Self) -> bool {
self.is_subset_of(other) && other.is_subset_of(self)
}
}