pub use crate::constraint::Relate;
pub use crate::domain::Domain;
pub use crate::set::{FromIndexKey, KeyCat, Set};
pub use crate::sum::__sum_over as sum_over;
pub use crate::sum::SumDomain;
#[must_use]
pub fn sum_terms<'a>(terms: Vec<oximo_expr::Expr<'a>>) -> oximo_expr::Expr<'a> {
terms.into_iter().sum()
}
pub fn filter_keys<K, F>(set: &Set<K>, pred: F) -> Set<K>
where
K: FromIndexKey,
F: FnMut(K) -> bool,
{
set.filter_typed(pred)
}
pub fn keys_of<K, D: SumDomain<K> + ?Sized>(d: &D) -> impl Iterator<Item = K> + '_ {
d.keys()
}
use num_traits::PrimInt;
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a valid index domain for a `variable!`/`constraint!` family",
label = "not an index domain",
note = "use a `Set`, an integer range `a..b` / `a..=b`, or a reference to one"
)]
pub trait IntoSet {
type Key;
fn into_set(self) -> Set<Self::Key>;
}
impl<K> IntoSet for Set<K> {
type Key = K;
fn into_set(self) -> Set<K> {
self
}
}
impl<T: PrimInt> IntoSet for std::ops::Range<T> {
type Key = usize;
fn into_set(self) -> Set<usize> {
Set::range(self)
}
}
impl<T: PrimInt> IntoSet for std::ops::RangeInclusive<T> {
type Key = usize;
fn into_set(self) -> Set<usize> {
let start = self.start().to_i64().expect("range start out of i64 range");
let end = self.end().to_i64().expect("range end out of i64 range");
Set::dense_i64(start, end.checked_add(1).expect("inclusive range end overflows i64"))
}
}
impl<S: IntoSet + Clone> IntoSet for &S {
type Key = S::Key;
fn into_set(self) -> Set<S::Key> {
(*self).clone().into_set()
}
}
pub fn as_set<S: IntoSet>(s: S) -> Set<S::Key> {
s.into_set()
}
#[must_use]
pub fn product<A, B>(a: &Set<A>, b: &Set<B>) -> Set<<A as KeyCat<B>>::Out>
where
A: KeyCat<B>,
{
Set::product(a, b)
}