oxilean_std/tactic_lemmas/
types.rs1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::functions::*;
8use std::collections::HashMap;
9
10#[allow(dead_code)]
14pub struct OmegaLinearExpr {
15 pub coeffs: Vec<i64>,
17 pub constant: i64,
19}
20#[allow(dead_code)]
21impl OmegaLinearExpr {
22 pub fn new(coeffs: Vec<i64>, constant: i64) -> Self {
24 Self { coeffs, constant }
25 }
26 pub fn eval(&self, vars: &[i64]) -> i64 {
28 self.coeffs
29 .iter()
30 .zip(vars.iter())
31 .map(|(c, v)| c * v)
32 .sum::<i64>()
33 + self.constant
34 }
35 pub fn is_trivially_nonpositive(&self) -> bool {
37 self.constant <= 0 && self.coeffs.iter().all(|&c| c == 0)
38 }
39 pub fn negate(&self) -> Self {
41 Self {
42 coeffs: self.coeffs.iter().map(|&c| -c).collect(),
43 constant: -self.constant,
44 }
45 }
46 pub fn add(&self, other: &Self) -> Self {
48 let len = self.coeffs.len().max(other.coeffs.len());
49 let mut coeffs = vec![0i64; len];
50 for (i, &c) in self.coeffs.iter().enumerate() {
51 coeffs[i] += c;
52 }
53 for (i, &c) in other.coeffs.iter().enumerate() {
54 coeffs[i] += c;
55 }
56 Self {
57 coeffs,
58 constant: self.constant + other.constant,
59 }
60 }
61}
62#[allow(dead_code)]
65pub struct LinarithCertificate {
66 pub multipliers: Vec<u64>,
68 pub hypotheses: Vec<OmegaLinearExpr>,
70}
71#[allow(dead_code)]
72impl LinarithCertificate {
73 pub fn new(multipliers: Vec<u64>, hypotheses: Vec<OmegaLinearExpr>) -> Self {
75 Self {
76 multipliers,
77 hypotheses,
78 }
79 }
80 pub fn is_valid_contradiction(&self, vars: &[i64]) -> bool {
83 if self.multipliers.len() != self.hypotheses.len() {
84 return false;
85 }
86 let combined_val: i64 = self
87 .multipliers
88 .iter()
89 .zip(self.hypotheses.iter())
90 .map(|(&m, hyp)| m as i64 * hyp.eval(vars))
91 .sum();
92 combined_val > 0
93 }
94 pub fn is_structurally_valid(&self) -> bool {
96 self.multipliers.len() == self.hypotheses.len()
97 }
98}
99#[allow(dead_code)]
103pub struct RingNfContext {
104 pub applied_axioms: Vec<String>,
106 pub carrier: String,
108}
109#[allow(dead_code)]
110impl RingNfContext {
111 pub fn new(carrier: &str) -> Self {
113 Self {
114 applied_axioms: Vec::new(),
115 carrier: carrier.to_string(),
116 }
117 }
118 pub fn apply_axiom(&mut self, axiom: &str) {
120 self.applied_axioms.push(axiom.to_string());
121 }
122 pub fn is_nontrivial(&self) -> bool {
124 !self.applied_axioms.is_empty()
125 }
126 pub fn step_count(&self) -> usize {
128 self.applied_axioms.len()
129 }
130 pub fn reset(&mut self) {
132 self.applied_axioms.clear();
133 }
134}
135#[allow(dead_code)]
137pub struct ExtendedSimpSet {
138 pub lemmas: Vec<(String, u64)>,
140 pub erased: Vec<String>,
142}
143#[allow(dead_code)]
144impl ExtendedSimpSet {
145 pub fn new() -> Self {
147 Self {
148 lemmas: Vec::new(),
149 erased: Vec::new(),
150 }
151 }
152 pub fn add_lemma(&mut self, name: &str, priority: u64) {
154 self.lemmas.push((name.to_string(), priority));
155 }
156 pub fn erase_lemma(&mut self, name: &str) {
158 self.erased.push(name.to_string());
159 }
160 pub fn is_active(&self, name: &str) -> bool {
162 let added = self.lemmas.iter().any(|(n, _)| n == name);
163 let erased = self.erased.iter().any(|n| n == name);
164 added && !erased
165 }
166 pub fn sorted_lemmas(&self) -> Vec<(String, u64)> {
168 let mut result: Vec<_> = self
169 .lemmas
170 .iter()
171 .filter(|(n, _)| !self.erased.contains(n))
172 .cloned()
173 .collect();
174 result.sort_by(|a, b| b.1.cmp(&a.1));
175 result
176 }
177 pub fn active_count(&self) -> usize {
179 self.lemmas
180 .iter()
181 .filter(|(n, _)| !self.erased.contains(n))
182 .count()
183 }
184}
185#[allow(dead_code)]
187pub struct PositivityChecker {
188 pub signs: std::collections::HashMap<String, i8>,
190}
191#[allow(dead_code)]
192impl PositivityChecker {
193 pub fn new() -> Self {
195 Self {
196 signs: std::collections::HashMap::new(),
197 }
198 }
199 pub fn record_sign(&mut self, expr: &str, sign: i8) {
201 self.signs.insert(expr.to_string(), sign);
202 }
203 pub fn is_nonneg(&self, expr: &str) -> bool {
205 match self.signs.get(expr) {
206 Some(&s) => s >= 0,
207 None => false,
208 }
209 }
210 pub fn product_nonneg(&self, a: &str, b: &str) -> bool {
212 let sa = self.signs.get(a).copied().unwrap_or(0);
213 let sb = self.signs.get(b).copied().unwrap_or(0);
214 (sa >= 0 && sb >= 0) || (sa <= 0 && sb <= 0)
215 }
216 pub fn sum_sign(&self, a: &str, b: &str) -> Option<i8> {
218 let sa = self.signs.get(a).copied()?;
219 let sb = self.signs.get(b).copied()?;
220 if sa >= 0 && sb >= 0 {
221 Some(1)
222 } else if sa < 0 && sb < 0 {
223 Some(-1)
224 } else {
225 None
226 }
227 }
228}
229#[allow(dead_code)]
234#[derive(Clone, Debug)]
235pub struct SimpLemmaEntry {
236 pub name: Name,
238 pub priority: u64,
240 pub proof: Expr,
242}
243impl SimpLemmaEntry {
244 #[allow(dead_code)]
246 pub fn mk(name: Name, priority: u64, proof: Expr) -> Self {
247 SimpLemmaEntry {
248 name,
249 priority,
250 proof,
251 }
252 }
253}
254#[allow(dead_code)]
258#[derive(Clone, Debug, Default)]
259pub struct SimpTheorems {
260 pub lemmas: Vec<SimpLemmaEntry>,
262}
263impl SimpTheorems {
264 #[allow(dead_code)]
266 pub fn empty() -> Self {
267 SimpTheorems { lemmas: vec![] }
268 }
269 #[allow(dead_code)]
271 pub fn add(&mut self, entry: SimpLemmaEntry) {
272 let pos = self
273 .lemmas
274 .iter()
275 .position(|e| e.priority < entry.priority)
276 .unwrap_or(self.lemmas.len());
277 self.lemmas.insert(pos, entry);
278 }
279 #[allow(dead_code)]
281 pub fn erase(&mut self, name: &Name) {
282 self.lemmas.retain(|e| &e.name != name);
283 }
284 #[allow(dead_code)]
286 pub fn len(&self) -> usize {
287 self.lemmas.len()
288 }
289 #[allow(dead_code)]
291 pub fn is_empty(&self) -> bool {
292 self.lemmas.is_empty()
293 }
294 #[allow(dead_code)]
296 pub fn get(&self, name: &Name) -> Option<&SimpLemmaEntry> {
297 self.lemmas.iter().find(|e| &e.name == name)
298 }
299}