Skip to content

Commit 3c377e4

Browse files
committed
Implement poly_simp_rel
1 parent 313feb5 commit 3c377e4

File tree

4 files changed

+53
-1
lines changed

4 files changed

+53
-1
lines changed

carcara/src/ast/macros.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ macro_rules! match_term {
174174
(@GET_VARIANT <=) => { $crate::ast::Operator::LessEq };
175175
(@GET_VARIANT >=) => { $crate::ast::Operator::GreaterEq };
176176

177+
(@GET_VARIANT to_real) => { $crate::ast::Operator::ToReal };
178+
177179
(@GET_VARIANT cl) => { $crate::ast::Operator::Cl };
178180
(@GET_VARIANT delete) => { $crate::ast::Operator::Delete };
179181

carcara/src/checker/error.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,15 @@ pub enum PolynomialError {
358358

359359
#[error("expected bitvector sort, got '{0}'")]
360360
ExpectedBvSort(Sort),
361+
362+
#[error("coefficient can't be zero: '{0}'")]
363+
CoeffIsZero(Rational),
364+
365+
#[error("coefficients should have the same signum: '{0}' and '{1}'")]
366+
CoeffDifferentSignums(Rational, Rational),
367+
368+
#[error("invalid relation operators: '{0}' and '{1}'")]
369+
InvalidOperators(Operator, Operator),
361370
}
362371

363372
/// Errors relevant to all rules that end subproofs (not just the `subproof` rule).

carcara/src/checker/rules/polynomial.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
use super::{assert_clause_len, RuleArgs, RuleResult};
1+
use super::{assert_clause_len, assert_eq, RuleArgs, RuleResult};
22
use crate::{
33
ast::{Operator, Rc, Sort, Term},
44
checker::error::PolynomialError,
5+
checker::rules::{assert_num_premises, get_premise_term},
56
};
67
use indexmap::{map::Entry, IndexMap};
78
use rug::{ops::NegAssign, Integer, Rational};
@@ -191,3 +192,42 @@ pub fn bv_poly_simp(RuleArgs { conclusion, pool, .. }: RuleArgs) -> RuleResult {
191192
Ok(())
192193
}
193194
}
195+
196+
pub fn poly_simp_rel(RuleArgs { conclusion, premises, .. }: RuleArgs) -> RuleResult {
197+
use Operator::*;
198+
199+
assert_num_premises(premises, 1)?;
200+
assert_clause_len(conclusion, 1)?;
201+
let prem = get_premise_term(&premises[0])?;
202+
203+
let ((c1, xs), (c2, ys)) = match_term_err!((= (* c1 xs) (* c2 ys)) = prem)?;
204+
let (x1, x2) =
205+
match_term_err!((to_real (- x1 x2)) = xs).or_else(|_| match_term_err!((- x1 x2) = xs))?;
206+
let (y1, y2) =
207+
match_term_err!((to_real (- y1 y2)) = ys).or_else(|_| match_term_err!((- y1 y2) = ys))?;
208+
209+
let (c1, c2) = (c1.as_fraction_err()?, c2.as_fraction_err()?);
210+
for c in [&c1, &c2] {
211+
rassert!(!c.is_zero(), PolynomialError::CoeffIsZero(c.clone()));
212+
}
213+
214+
let (left, right) = match_term_err!((= l r) = &conclusion[0])?;
215+
match (left.as_op_err()?, right.as_op_err()?) {
216+
(
217+
(op @ (LessThan | LessEq | Equals | GreaterEq | GreaterThan), [l1, l2]),
218+
(op2, [r1, r2]),
219+
) if op2 == op => {
220+
rassert!(
221+
op == Equals || c1.is_positive() == c2.is_positive(),
222+
PolynomialError::CoeffDifferentSignums(c1.clone(), c2.clone()),
223+
);
224+
225+
assert_eq(l1, x1)?;
226+
assert_eq(l2, x2)?;
227+
assert_eq(r1, y1)?;
228+
assert_eq(r2, y2)?;
229+
Ok(())
230+
}
231+
((op1, _), (op2, _)) => Err(PolynomialError::InvalidOperators(op1, op2).into()),
232+
}
233+
}

carcara/src/checker/shared.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ pub fn get_rule_shared(rule_name: &str, elaborated: bool) -> Option<crate::check
204204
"la_tautology" => linear_arithmetic::la_tautology,
205205
"poly_simp" => polynomial::poly_simp,
206206
"bv_poly_simp" => polynomial::bv_poly_simp,
207+
"poly_simp_rel" => polynomial::poly_simp_rel,
207208
"forall_inst" => quantifier::forall_inst,
208209
"qnt_join" => quantifier::qnt_join,
209210
"qnt_rm_unused" => quantifier::qnt_rm_unused,

0 commit comments

Comments
 (0)