use super::functions::*;
#[allow(dead_code)]
pub struct WqoInstance {
pub carrier: Vec<u64>,
pub le_matrix: Vec<Vec<bool>>,
}
#[allow(dead_code)]
impl WqoInstance {
pub fn new(carrier: Vec<u64>, le: impl Fn(u64, u64) -> bool) -> Self {
let n = carrier.len();
let mut le_matrix = vec![vec![false; n]; n];
for i in 0..n {
for j in 0..n {
le_matrix[i][j] = le(carrier[i], carrier[j]);
}
}
Self { carrier, le_matrix }
}
pub fn has_good_pair(&self, seq: &[usize]) -> bool {
for i in 0..seq.len() {
for j in (i + 1)..seq.len() {
if self.le_matrix[seq[i]][seq[j]] {
return true;
}
}
}
false
}
pub fn find_good_pair(&self, seq: &[usize]) -> Option<(usize, usize)> {
for i in 0..seq.len() {
for j in (i + 1)..seq.len() {
if self.le_matrix[seq[i]][seq[j]] {
return Some((i, j));
}
}
}
None
}
pub fn size(&self) -> usize {
self.carrier.len()
}
pub fn is_reflexive(&self) -> bool {
(0..self.size()).all(|i| self.le_matrix[i][i])
}
pub fn is_transitive(&self) -> bool {
let n = self.size();
for i in 0..n {
for j in 0..n {
for k in 0..n {
if self.le_matrix[i][j] && self.le_matrix[j][k] && !self.le_matrix[i][k] {
return false;
}
}
}
}
true
}
}
#[allow(dead_code)]
pub struct FiniteLinearOrder {
pub size: usize,
pub order: Vec<usize>,
}
#[allow(dead_code)]
impl FiniteLinearOrder {
pub fn identity(n: usize) -> Self {
Self {
size: n,
order: (0..n).collect(),
}
}
pub fn from_permutation(perm: Vec<usize>) -> Option<Self> {
let n = perm.len();
let mut seen = vec![false; n];
for &x in &perm {
if x >= n || seen[x] {
return None;
}
seen[x] = true;
}
Some(Self {
size: n,
order: perm,
})
}
pub fn compare(&self, a: usize, b: usize) -> Ordering {
let rank_a = self.order.iter().position(|&x| x == a);
let rank_b = self.order.iter().position(|&x| x == b);
match (rank_a, rank_b) {
(Some(ra), Some(rb)) => Ordering::from_std(ra.cmp(&rb)),
_ => Ordering::Equal,
}
}
pub fn rank(&self, a: usize) -> Option<usize> {
self.order.iter().position(|&x| x == a)
}
pub fn min_elem(&self) -> Option<usize> {
self.order.first().copied()
}
pub fn max_elem(&self) -> Option<usize> {
self.order.last().copied()
}
pub fn is_well_founded(&self) -> bool {
true
}
pub fn reverse_order(&self) -> FiniteLinearOrder {
let mut rev = self.order.clone();
rev.reverse();
FiniteLinearOrder {
size: self.size,
order: rev,
}
}
}
#[derive(Clone, Debug)]
pub struct OrderingBuilder {
result: Ordering,
}
impl OrderingBuilder {
pub fn new() -> Self {
Self {
result: Ordering::Equal,
}
}
pub fn then(mut self, next: Ordering) -> Self {
self.result = self.result.then(next);
self
}
pub fn then_with<F: FnOnce() -> Ordering>(mut self, f: F) -> Self {
self.result = self.result.then_with(f);
self
}
pub fn field<T: std::cmp::Ord>(self, a: &T, b: &T) -> Self {
self.then(cmp(a, b))
}
pub fn build(self) -> Ordering {
self.result
}
}
#[allow(dead_code)]
pub struct OrderedRange<T: std::cmp::Ord + Clone> {
pub lo: T,
pub hi: T,
}
#[allow(dead_code)]
impl<T: std::cmp::Ord + Clone> OrderedRange<T> {
pub fn new(lo: T, hi: T) -> Self {
assert!(lo <= hi, "lower bound must not exceed upper bound");
Self { lo, hi }
}
pub fn contains(&self, x: &T) -> bool {
x >= &self.lo && x <= &self.hi
}
pub fn contains_range(&self, other: &OrderedRange<T>) -> bool {
other.lo >= self.lo && other.hi <= self.hi
}
pub fn overlaps(&self, other: &OrderedRange<T>) -> bool {
self.lo <= other.hi && other.lo <= self.hi
}
pub fn lower(&self) -> &T {
&self.lo
}
pub fn upper(&self) -> &T {
&self.hi
}
}
#[allow(dead_code)]
pub struct OrdinalCnf {
pub terms: Vec<(u64, u64)>,
}
#[allow(dead_code)]
impl OrdinalCnf {
pub fn zero() -> Self {
Self { terms: vec![] }
}
pub fn finite(n: u64) -> Self {
if n == 0 {
Self::zero()
} else {
Self {
terms: vec![(0, n)],
}
}
}
pub fn omega() -> Self {
Self {
terms: vec![(1, 1)],
}
}
pub fn omega_pow(k: u64) -> Self {
Self {
terms: vec![(k, 1)],
}
}
pub fn is_zero(&self) -> bool {
self.terms.is_empty()
}
pub fn is_finite(&self) -> bool {
self.terms.is_empty() || (self.terms.len() == 1 && self.terms[0].0 == 0)
}
pub fn as_finite(&self) -> Option<u64> {
if self.terms.is_empty() {
Some(0)
} else if self.terms.len() == 1 && self.terms[0].0 == 0 {
Some(self.terms[0].1)
} else {
None
}
}
pub fn add(&self, other: &OrdinalCnf) -> OrdinalCnf {
if other.is_zero() {
return OrdinalCnf {
terms: self.terms.clone(),
};
}
if self.is_zero() {
return OrdinalCnf {
terms: other.terms.clone(),
};
}
let leading_exp = other.terms[0].0;
let mut result: Vec<(u64, u64)> = self
.terms
.iter()
.filter(|(e, _)| *e > leading_exp)
.cloned()
.collect();
result.extend_from_slice(&other.terms);
OrdinalCnf { terms: result }
}
pub fn ord_cmp(&self, other: &OrdinalCnf) -> Ordering {
for (a, b) in self.terms.iter().zip(other.terms.iter()) {
match a.0.cmp(&b.0) {
std::cmp::Ordering::Greater => return Ordering::Greater,
std::cmp::Ordering::Less => return Ordering::Less,
std::cmp::Ordering::Equal => match a.1.cmp(&b.1) {
std::cmp::Ordering::Greater => return Ordering::Greater,
std::cmp::Ordering::Less => return Ordering::Less,
std::cmp::Ordering::Equal => {}
},
}
}
Ordering::from_std(self.terms.len().cmp(&other.terms.len()))
}
pub fn num_terms(&self) -> usize {
self.terms.len()
}
}
#[allow(dead_code)]
pub struct OrderedTable<K: std::cmp::Ord, V> {
entries: Vec<(K, V)>,
}
#[allow(dead_code)]
impl<K: std::cmp::Ord, V> OrderedTable<K, V> {
pub fn new() -> Self {
Self {
entries: Vec::new(),
}
}
pub fn insert(&mut self, key: K, value: V) {
let pos = self.entries.partition_point(|(k, _)| *k < key);
self.entries.insert(pos, (key, value));
}
pub fn get(&self, key: &K) -> Option<&V> {
let pos = self.entries.partition_point(|(k, _)| k < key);
if pos < self.entries.len() && self.entries[pos].0 == *key {
Some(&self.entries[pos].1)
} else {
None
}
}
pub fn remove(&mut self, key: &K) -> Option<V> {
let pos = self.entries.partition_point(|(k, _)| k < key);
if pos < self.entries.len() && self.entries[pos].0 == *key {
Some(self.entries.remove(pos).1)
} else {
None
}
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
self.entries.iter().map(|(k, v)| (k, v))
}
pub fn contains_key(&self, key: &K) -> bool {
self.get(key).is_some()
}
pub fn keys(&self) -> Vec<&K> {
self.entries.iter().map(|(k, _)| k).collect()
}
pub fn values(&self) -> Vec<&V> {
self.entries.iter().map(|(_, v)| v).collect()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Ordering {
Less,
Equal,
Greater,
}
impl Ordering {
pub fn reverse(self) -> Self {
match self {
Ordering::Less => Ordering::Greater,
Ordering::Equal => Ordering::Equal,
Ordering::Greater => Ordering::Less,
}
}
pub fn then(self, other: Ordering) -> Self {
match self {
Ordering::Equal => other,
_ => self,
}
}
pub fn then_with<F: FnOnce() -> Ordering>(self, f: F) -> Self {
match self {
Ordering::Equal => f(),
_ => self,
}
}
pub fn is_lt(self) -> bool {
self == Ordering::Less
}
pub fn is_eq(self) -> bool {
self == Ordering::Equal
}
pub fn is_gt(self) -> bool {
self == Ordering::Greater
}
pub fn is_le(self) -> bool {
self != Ordering::Greater
}
pub fn is_ge(self) -> bool {
self != Ordering::Less
}
pub fn to_signum(self) -> i32 {
match self {
Ordering::Less => -1,
Ordering::Equal => 0,
Ordering::Greater => 1,
}
}
pub fn from_signum(n: i32) -> Self {
match n.cmp(&0) {
std::cmp::Ordering::Less => Ordering::Less,
std::cmp::Ordering::Equal => Ordering::Equal,
std::cmp::Ordering::Greater => Ordering::Greater,
}
}
pub fn from_std(o: std::cmp::Ordering) -> Self {
match o {
std::cmp::Ordering::Less => Ordering::Less,
std::cmp::Ordering::Equal => Ordering::Equal,
std::cmp::Ordering::Greater => Ordering::Greater,
}
}
pub fn to_std(self) -> std::cmp::Ordering {
match self {
Ordering::Less => std::cmp::Ordering::Less,
Ordering::Equal => std::cmp::Ordering::Equal,
Ordering::Greater => std::cmp::Ordering::Greater,
}
}
}
#[allow(dead_code)]
pub struct DedekindCutQ {
pub numerator: i64,
pub denominator: u64,
}
#[allow(dead_code)]
impl DedekindCutQ {
pub fn new(p: i64, q: u64) -> Self {
assert!(q > 0, "denominator must be positive");
Self {
numerator: p,
denominator: q,
}
}
pub fn in_lower(&self, r: i64, s: u64) -> bool {
r * (self.denominator as i64) < self.numerator * (s as i64)
}
pub fn in_upper(&self, r: i64, s: u64) -> bool {
r * (self.denominator as i64) > self.numerator * (s as i64)
}
pub fn as_f64(&self) -> f64 {
self.numerator as f64 / self.denominator as f64
}
pub fn cut_cmp(&self, other: &DedekindCutQ) -> Ordering {
let lhs = self.numerator * (other.denominator as i64);
let rhs = other.numerator * (self.denominator as i64);
Ordering::from_std(lhs.cmp(&rhs))
}
pub fn mediant(&self, other: &DedekindCutQ) -> DedekindCutQ {
DedekindCutQ::new(
self.numerator + other.numerator,
self.denominator + other.denominator,
)
}
}
#[allow(dead_code)]
pub struct FinitePartialOrder {
pub size: usize,
pub le: Vec<Vec<bool>>,
}
#[allow(dead_code)]
impl FinitePartialOrder {
pub fn discrete(n: usize) -> Self {
let mut le = vec![vec![false; n]; n];
for i in 0..n {
le[i][i] = true;
}
Self { size: n, le }
}
pub fn is_reflexive(&self) -> bool {
(0..self.size).all(|i| self.le[i][i])
}
pub fn is_antisymmetric(&self) -> bool {
for i in 0..self.size {
for j in 0..self.size {
if i != j && self.le[i][j] && self.le[j][i] {
return false;
}
}
}
true
}
pub fn is_transitive(&self) -> bool {
let n = self.size;
for i in 0..n {
for j in 0..n {
for k in 0..n {
if self.le[i][j] && self.le[j][k] && !self.le[i][k] {
return false;
}
}
}
}
true
}
pub fn is_valid(&self) -> bool {
self.is_reflexive() && self.is_antisymmetric() && self.is_transitive()
}
pub fn is_total(&self) -> bool {
for i in 0..self.size {
for j in 0..self.size {
if !self.le[i][j] && !self.le[j][i] {
return false;
}
}
}
true
}
pub fn maximal_elements(&self) -> Vec<usize> {
(0..self.size)
.filter(|&i| (0..self.size).all(|j| !self.le[i][j] || i == j || self.le[j][i]))
.collect()
}
pub fn transitive_closure(&self) -> FinitePartialOrder {
let n = self.size;
let mut le = self.le.clone();
for k in 0..n {
for i in 0..n {
for j in 0..n {
if le[i][k] && le[k][j] {
le[i][j] = true;
}
}
}
}
FinitePartialOrder { size: n, le }
}
}