From 0578e99dc27c512f894805766674e6baa2b9a62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Fri, 22 May 2020 18:14:56 +0200 Subject: [PATCH] Finish basic simplifications --- src/commands/verify_program.rs | 17 +++++- src/main.rs | 7 ++- src/problem.rs | 33 ++++++++--- src/simplify.rs | 89 +++++++++++++++++++----------- src/translate/verify_properties.rs | 6 +- 5 files changed, 103 insertions(+), 49 deletions(-) diff --git a/src/commands/verify_program.rs b/src/commands/verify_program.rs index 1bc4710..4f79464 100644 --- a/src/commands/verify_program.rs +++ b/src/commands/verify_program.rs @@ -1,5 +1,5 @@ -pub fn run

(program_path: P, specification_path: P, proof_direction: - crate::problem::ProofDirection) +pub fn run

(program_path: P, specification_path: P, + proof_direction: crate::problem::ProofDirection, no_simplify: bool) where P: AsRef, { @@ -60,6 +60,19 @@ where } } + if !no_simplify + { + match problem.simplify() + { + Ok(_) => (), + Err(error) => + { + log::error!("could not simplify translated program: {}", error); + std::process::exit(1) + } + } + } + match problem.prove(proof_direction) { Ok(()) => (), diff --git a/src/main.rs b/src/main.rs index ed5c583..3ed04d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,10 @@ enum Command /// Proof direction (forward, backward, both) #[structopt(long, default_value = "forward")] proof_direction: anthem::problem::ProofDirection, + + /// Do not simplify translated program + #[structopt(long)] + no_simplify: bool, } } @@ -35,8 +39,9 @@ fn main() program_path, specification_path, proof_direction, + no_simplify, } => anthem::commands::verify_program::run(&program_path, &specification_path, - proof_direction), + proof_direction, no_simplify), } } diff --git a/src/problem.rs b/src/problem.rs index d2c2c9d..c49572a 100644 --- a/src/problem.rs +++ b/src/problem.rs @@ -44,7 +44,7 @@ impl Problem } } - pub(crate) fn add_statement(&self, section_kind: SectionKind, mut statement: Statement) + pub(crate) fn add_statement(&self, section_kind: SectionKind, statement: Statement) { let mut statements = self.statements.borrow_mut(); let section = statements.entry(section_kind).or_insert(vec![]); @@ -151,6 +151,28 @@ impl Problem Ok(()) } + pub fn simplify(&mut self) -> Result<(), crate::Error> + { + let mut statements = self.statements.borrow_mut(); + + for (_, statements) in statements.iter_mut() + { + for statement in statements.iter_mut() + { + match statement.kind + { + // Only simplify generated formulas + | StatementKind::CompletedDefinition(_) + | StatementKind::IntegrityConstraint => + crate::simplify(&mut statement.formula)?, + _ => (), + } + } + } + + Ok(()) + } + fn print_step_title(&self, step_title: &str, color: &termcolor::ColorSpec) -> Result<(), crate::Error> { @@ -319,13 +341,8 @@ impl Problem self.shell.borrow_mut().print(&format!("{}: ", statement.kind), &termcolor::ColorSpec::new())?; - match statement.kind - { - StatementKind::CompletedDefinition(_) - | StatementKind::IntegrityConstraint => - crate::autoname_variables(&mut statement.formula), - _ => (), - } + // TODO: only perform autonaming when necessary + crate::autoname_variables(&mut statement.formula); print!("{}", statement.formula); diff --git a/src/simplify.rs b/src/simplify.rs index b14f189..200b28c 100644 --- a/src/simplify.rs +++ b/src/simplify.rs @@ -18,9 +18,10 @@ impl SimplificationResult } } -fn remove_unnecessary_exists_parameters(formula: &mut crate::Formula) -> SimplificationResult +fn remove_unnecessary_exists_parameters(formula: &mut crate::Formula) + -> Result { - use crate::Formula; + use crate::{Formula, Term}; match formula { @@ -33,18 +34,18 @@ fn remove_unnecessary_exists_parameters(formula: &mut crate::Formula) -> Simplif for argument in arguments { simplification_result = simplification_result.or( - remove_unnecessary_exists_parameters(argument)); + remove_unnecessary_exists_parameters(argument)?); } - simplification_result + Ok(simplification_result) }, Formula::Boolean(_) | Formula::Compare(_) - | Formula::Predicate(_) => SimplificationResult::NotSimplified, + | Formula::Predicate(_) => Ok(SimplificationResult::NotSimplified), Formula::Exists(ref mut quantified_formula) => { let mut simplification_result = - remove_unnecessary_exists_parameters(&mut quantified_formula.argument); + remove_unnecessary_exists_parameters(&mut quantified_formula.argument)?; let arguments = match *quantified_formula.argument { @@ -69,31 +70,55 @@ fn remove_unnecessary_exists_parameters(formula: &mut crate::Formula) -> Simplif _ => return None, }; - if let foliage::Term::Variable(ref variable) = **left + let assigned_term = match (&**left, &**right) { - if variable.declaration == *parameter - && !crate::term_contains_variable(right, parameter) + (Term::Variable(ref variable), right) + if variable.declaration == *parameter => + right, + (left, Term::Variable(ref variable)) + if variable.declaration == *parameter => + left, + _ => return None, + }; + + let parameter_domain = match parameter.domain() + { + Ok(domain) => domain, + Err(_) => + unreachable!("all variable domains should be assigned at this point"), + }; + + let is_parameter_integer = + parameter_domain == crate::Domain::Integer; + + let is_assigned_term_arithmetic = + match crate::is_term_arithmetic(assigned_term) { - // TODO: avoid copy - return Some((argument_index, crate::copy_term(right))); - } + Ok(is_term_arithmetic) => is_term_arithmetic, + Err(error) => return Some(Err(error)), + }; + + let is_assignment_narrowing = is_parameter_integer + && !is_assigned_term_arithmetic; + + if crate::term_contains_variable(assigned_term, parameter) + || is_assignment_narrowing + { + return None; } - if let foliage::Term::Variable(ref variable) = **right - { - if variable.declaration == *parameter - && !crate::term_contains_variable(left, parameter) - { - // TODO: avoid copy - return Some((argument_index, crate::copy_term(left))); - } - } - - None + // TODO: avoid copy + Some(Ok((argument_index, crate::copy_term(assigned_term)))) }); - if let Some((assignment_index, assigned_term)) = assignment + if let Some(assignment) = assignment { + let (assignment_index, assigned_term) = match assignment + { + Err(error) => return Some(Err(error)), + Ok(assignment) => assignment, + }; + arguments.remove(assignment_index); for argument in arguments.iter_mut() @@ -107,11 +132,11 @@ fn remove_unnecessary_exists_parameters(formula: &mut crate::Formula) -> Simplif return None; } - Some(std::rc::Rc::clone(parameter)) + Some(Ok(std::rc::Rc::clone(parameter))) }) - .collect()); + .collect::>()?); - simplification_result + Ok(simplification_result) } Formula::ForAll(ref mut quantified_formula) => remove_unnecessary_exists_parameters(&mut quantified_formula.argument), @@ -225,22 +250,20 @@ fn simplify_trivial_n_ary_formulas(formula: &mut crate::Formula) -> Simplificati } } -pub(crate) fn simplify(formula: &mut crate::Formula) +pub(crate) fn simplify(formula: &mut crate::Formula) -> Result<(), crate::Error> { loop { - if remove_unnecessary_exists_parameters(formula) == SimplificationResult::Simplified + if remove_unnecessary_exists_parameters(formula)? == SimplificationResult::Simplified || simplify_quantified_formulas_without_parameters(formula) == SimplificationResult::Simplified || simplify_trivial_n_ary_formulas(formula) == SimplificationResult::Simplified { - log::debug!("cool, simplified!"); - continue; } - log::debug!("nope, that’s it"); - break; } + + Ok(()) } diff --git a/src/translate/verify_properties.rs b/src/translate/verify_properties.rs index 925bd12..bd9458c 100644 --- a/src/translate/verify_properties.rs +++ b/src/translate/verify_properties.rs @@ -146,11 +146,9 @@ impl<'p> Translator<'p> let statement_kind = crate::problem::StatementKind::CompletedDefinition( std::rc::Rc::clone(&predicate_declaration)); - let mut completed_definition = completed_definition(predicate_declaration, + let completed_definition = completed_definition(predicate_declaration, &mut self.definitions); - //crate::simplify(&mut completed_definition); - let statement_name = format!("completed_definition_{}", predicate_declaration.tptp_statement_name()); @@ -287,8 +285,6 @@ impl<'p> Translator<'p> let integrity_constraint = crate::universal_closure(open_formula); - //crate::simplify(&mut integrity_constraint); - let statement = crate::problem::Statement::new( crate::problem::StatementKind::IntegrityConstraint, integrity_constraint) .with_name("integrity_constraint".to_string());