use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use super::functions::*;
use std::collections::HashMap;
#[allow(dead_code)]
pub struct OmegaLinearExpr {
pub coeffs: Vec<i64>,
pub constant: i64,
}
#[allow(dead_code)]
impl OmegaLinearExpr {
pub fn new(coeffs: Vec<i64>, constant: i64) -> Self {
Self { coeffs, constant }
}
pub fn eval(&self, vars: &[i64]) -> i64 {
self.coeffs
.iter()
.zip(vars.iter())
.map(|(c, v)| c * v)
.sum::<i64>()
+ self.constant
}
pub fn is_trivially_nonpositive(&self) -> bool {
self.constant <= 0 && self.coeffs.iter().all(|&c| c == 0)
}
pub fn negate(&self) -> Self {
Self {
coeffs: self.coeffs.iter().map(|&c| -c).collect(),
constant: -self.constant,
}
}
pub fn add(&self, other: &Self) -> Self {
let len = self.coeffs.len().max(other.coeffs.len());
let mut coeffs = vec![0i64; len];
for (i, &c) in self.coeffs.iter().enumerate() {
coeffs[i] += c;
}
for (i, &c) in other.coeffs.iter().enumerate() {
coeffs[i] += c;
}
Self {
coeffs,
constant: self.constant + other.constant,
}
}
}
#[allow(dead_code)]
pub struct LinarithCertificate {
pub multipliers: Vec<u64>,
pub hypotheses: Vec<OmegaLinearExpr>,
}
#[allow(dead_code)]
impl LinarithCertificate {
pub fn new(multipliers: Vec<u64>, hypotheses: Vec<OmegaLinearExpr>) -> Self {
Self {
multipliers,
hypotheses,
}
}
pub fn is_valid_contradiction(&self, vars: &[i64]) -> bool {
if self.multipliers.len() != self.hypotheses.len() {
return false;
}
let combined_val: i64 = self
.multipliers
.iter()
.zip(self.hypotheses.iter())
.map(|(&m, hyp)| m as i64 * hyp.eval(vars))
.sum();
combined_val > 0
}
pub fn is_structurally_valid(&self) -> bool {
self.multipliers.len() == self.hypotheses.len()
}
}
#[allow(dead_code)]
pub struct RingNfContext {
pub applied_axioms: Vec<String>,
pub carrier: String,
}
#[allow(dead_code)]
impl RingNfContext {
pub fn new(carrier: &str) -> Self {
Self {
applied_axioms: Vec::new(),
carrier: carrier.to_string(),
}
}
pub fn apply_axiom(&mut self, axiom: &str) {
self.applied_axioms.push(axiom.to_string());
}
pub fn is_nontrivial(&self) -> bool {
!self.applied_axioms.is_empty()
}
pub fn step_count(&self) -> usize {
self.applied_axioms.len()
}
pub fn reset(&mut self) {
self.applied_axioms.clear();
}
}
#[allow(dead_code)]
pub struct ExtendedSimpSet {
pub lemmas: Vec<(String, u64)>,
pub erased: Vec<String>,
}
#[allow(dead_code)]
impl ExtendedSimpSet {
pub fn new() -> Self {
Self {
lemmas: Vec::new(),
erased: Vec::new(),
}
}
pub fn add_lemma(&mut self, name: &str, priority: u64) {
self.lemmas.push((name.to_string(), priority));
}
pub fn erase_lemma(&mut self, name: &str) {
self.erased.push(name.to_string());
}
pub fn is_active(&self, name: &str) -> bool {
let added = self.lemmas.iter().any(|(n, _)| n == name);
let erased = self.erased.iter().any(|n| n == name);
added && !erased
}
pub fn sorted_lemmas(&self) -> Vec<(String, u64)> {
let mut result: Vec<_> = self
.lemmas
.iter()
.filter(|(n, _)| !self.erased.contains(n))
.cloned()
.collect();
result.sort_by_key(|b| std::cmp::Reverse(b.1));
result
}
pub fn active_count(&self) -> usize {
self.lemmas
.iter()
.filter(|(n, _)| !self.erased.contains(n))
.count()
}
}
#[allow(dead_code)]
pub struct PositivityChecker {
pub signs: std::collections::HashMap<String, i8>,
}
#[allow(dead_code)]
impl PositivityChecker {
pub fn new() -> Self {
Self {
signs: std::collections::HashMap::new(),
}
}
pub fn record_sign(&mut self, expr: &str, sign: i8) {
self.signs.insert(expr.to_string(), sign);
}
pub fn is_nonneg(&self, expr: &str) -> bool {
match self.signs.get(expr) {
Some(&s) => s >= 0,
None => false,
}
}
pub fn product_nonneg(&self, a: &str, b: &str) -> bool {
let sa = self.signs.get(a).copied().unwrap_or(0);
let sb = self.signs.get(b).copied().unwrap_or(0);
(sa >= 0 && sb >= 0) || (sa <= 0 && sb <= 0)
}
pub fn sum_sign(&self, a: &str, b: &str) -> Option<i8> {
let sa = self.signs.get(a).copied()?;
let sb = self.signs.get(b).copied()?;
if sa >= 0 && sb >= 0 {
Some(1)
} else if sa < 0 && sb < 0 {
Some(-1)
} else {
None
}
}
}
#[allow(dead_code)]
#[derive(Clone, Debug)]
pub struct SimpLemmaEntry {
pub name: Name,
pub priority: u64,
pub proof: Expr,
}
impl SimpLemmaEntry {
#[allow(dead_code)]
pub fn mk(name: Name, priority: u64, proof: Expr) -> Self {
SimpLemmaEntry {
name,
priority,
proof,
}
}
}
#[allow(dead_code)]
#[derive(Clone, Debug, Default)]
pub struct SimpTheorems {
pub lemmas: Vec<SimpLemmaEntry>,
}
impl SimpTheorems {
#[allow(dead_code)]
pub fn empty() -> Self {
SimpTheorems { lemmas: vec![] }
}
#[allow(dead_code)]
pub fn add(&mut self, entry: SimpLemmaEntry) {
let pos = self
.lemmas
.iter()
.position(|e| e.priority < entry.priority)
.unwrap_or(self.lemmas.len());
self.lemmas.insert(pos, entry);
}
#[allow(dead_code)]
pub fn erase(&mut self, name: &Name) {
self.lemmas.retain(|e| &e.name != name);
}
#[allow(dead_code)]
pub fn len(&self) -> usize {
self.lemmas.len()
}
#[allow(dead_code)]
pub fn is_empty(&self) -> bool {
self.lemmas.is_empty()
}
#[allow(dead_code)]
pub fn get(&self, name: &Name) -> Option<&SimpLemmaEntry> {
self.lemmas.iter().find(|e| &e.name == name)
}
}