use crate::{
DataSet,
ItemSet,
Support,
closed::{
InitialSets,
is_dup
}
};
pub fn closed<D>(dataset: &D, min_sup: usize) -> Box<[(D::ItemSet, Support)]>
where
D: DataSet + Sync,
D::ItemSet: Send + Sync,
for<'a> &'a D::ItemSet: IntoIterator<Item = usize>
{
const CHANNEL_BOUND: usize = 8192;
let InitialSets { closed, pre, post } = InitialSets::new(dataset, min_sup);
let closed_set = closed.clone();
let transactions_count = dataset.transactions_count();
let (tx, rx) = std::sync::mpsc::sync_channel(CHANNEL_BOUND);
let collector = std::thread::spawn(
move || -> Box<[(D::ItemSet, Support)]> { let mut vec = vec![(closed_set, transactions_count)];
vec.extend(rx.iter());
vec.into_boxed_slice()
}
);
rayon::scope(
|scope| _closed(
dataset,
min_sup,
&closed,
pre,
&post,
&tx,
scope,
)
);
drop(tx);
collector
.join()
.expect("Failed to join collector thread") }
fn _closed<'a, D>(
dataset: &'a D,
min_sup: usize,
closed_set: &D::ItemSet,
mut pre_set: D::ItemSet,
post_set: &D::ItemSet,
out: &'a std::sync::mpsc::SyncSender<(D::ItemSet, Support)>,
scope: &rayon::Scope<'a>,
)
where
D: DataSet + Sync,
D::ItemSet: Send + Sync,
for<'b> &'b D::ItemSet: IntoIterator<Item = usize>
{
for i in post_set.into_iter() {
let mut new_gen = closed_set.clone();
new_gen.add(i);
let new_gen_cover = dataset.cover(&new_gen);
if dataset.support(&new_gen) >= min_sup {
if !is_dup(dataset, &new_gen_cover, &pre_set) {
let mut closed_set_new = new_gen.clone();
let mut post_set_new = D::ItemSet::empty();
for j in post_set.into_iter().skip_while(|&j| i >= j) {
if dataset.supports(j, &new_gen_cover) {
closed_set_new.add(j);
}
else {
post_set_new.add(j)
}
}
out
.send(
(
closed_set_new.clone(),
dataset.support(&closed_set_new)
)
)
.expect("Failed to send result");
let pre_set_new = pre_set.clone();
scope.spawn(
move |scope| _closed(
dataset,
min_sup,
&closed_set_new,
pre_set_new,
&post_set_new,
out,
scope
)
);
pre_set.add(i);
}
}
}
}