use crate::types::PointCount;
use crate::{ClusteringProblem, ColoredMetric, OptionalParameters};
pub fn assert_clustering_problem<M: ColoredMetric>(
space: &M,
prob: &ClusteringProblem,
) -> Result<(), String> {
assert_problem_parameters(prob)?;
if space.n() < prob.k {
return Err(format!(
"We have n < k ({} < {})! We need more points than centers.",
space.n(),
prob.k
));
};
if space.n() < prob.k * prob.privacy_bound {
return Err(format!("We have n < k * L ({} < {} * {})! We need enough points so that k center can satisfy the privacy condition.", space.n(), prob.k, prob.privacy_bound));
};
let mut number_of_points_of_color: Vec<PointCount> = vec![0; space.gamma()];
for p in space.point_iter() {
number_of_points_of_color[space.color(p)] += 1;
}
let restricted_colors = if space.gamma() < prob.rep_intervals.len() {
space.gamma()
} else {
prob.rep_intervals.len()
};
for (c, color) in number_of_points_of_color
.iter()
.enumerate()
.take(restricted_colors)
{
if *color < prob.rep_intervals[c].0 {
return Err(format!("There are {} points of color {}, but we require a = {} of the centers to be of this color.", number_of_points_of_color[c], c, prob.rep_intervals[c].0));
};
}
for c in restricted_colors..prob.rep_intervals.len() {
if prob.rep_intervals[c].0 != 0 {
return Err(format!("We want {} centers of color {}, but there is not a single point of that color. We have gamma = {}.", prob.rep_intervals[c].0, c, space.gamma()));
};
}
let mut sum_of_b = 0;
(0..restricted_colors).for_each(|c| {
let upper_bound = if prob.rep_intervals[c].1 < number_of_points_of_color[c] {
prob.rep_intervals[c].1
} else {
number_of_points_of_color[c]
};
sum_of_b += upper_bound;
});
(restricted_colors..space.gamma()).for_each(|c| {
sum_of_b += number_of_points_of_color[c];
});
if sum_of_b < prob.k {
return Err(format!("The sum of the upper bounds of the representative intervals (or the number of points of that color) is {}, which is smaller than k = {}.", sum_of_b, prob.k));
};
Ok(())
}
pub(crate) fn assert_problem_parameters(prob: &ClusteringProblem) -> Result<(), String> {
if prob.k < 1 {
return Err(format!(
"We have k = {}! There should be at least one center.",
prob.k
));
};
for (c, interval) in prob.rep_intervals.iter().enumerate() {
if interval.0 > interval.1 {
return Err(format!("The interval of color {} is ({}, {}). Lower bound cannot be bigger than the upper bound.", c, interval.0, interval.1));
};
}
let mut sum_of_a = 0;
for (a, _) in prob.rep_intervals.iter() {
sum_of_a += a;
}
if sum_of_a > prob.k {
return Err(format!("The sum of the lower bounds of the representative intervals is {}, which is larger than k = {}.", sum_of_a, prob.k));
};
Ok(())
}
pub(crate) fn assert_optional_parameters(para: &OptionalParameters) -> Result<(), String> {
if let Some(i) = para.verbose {
if i > 2 {
return Err(String::from(
"The verbose parameter must be 0 (silent), 1 (brief) or 2 (verbose).",
));
}
};
if let Some(i) = para.thread_count {
if i <= 1 {
return Err(String::from("There need to be at least two threads."));
}
};
Ok(())
}