Start implementation of simplifications
This commit is contained in:
parent
d77c7648b3
commit
86d2857494
@ -6,11 +6,13 @@ pub mod error;
|
|||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod output;
|
pub mod output;
|
||||||
pub mod problem;
|
pub mod problem;
|
||||||
|
pub mod simplify;
|
||||||
pub(crate) mod traits;
|
pub(crate) mod traits;
|
||||||
pub mod translate;
|
pub mod translate;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use problem::Problem;
|
pub use problem::Problem;
|
||||||
|
pub(crate) use simplify::*;
|
||||||
pub(crate) use utils::*;
|
pub(crate) use utils::*;
|
||||||
pub use utils::Domain;
|
pub use utils::Domain;
|
||||||
|
246
src/simplify.rs
Normal file
246
src/simplify.rs
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
|
enum SimplificationResult
|
||||||
|
{
|
||||||
|
Simplified,
|
||||||
|
NotSimplified,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimplificationResult
|
||||||
|
{
|
||||||
|
fn or(&self, other: SimplificationResult) -> SimplificationResult
|
||||||
|
{
|
||||||
|
match (self, other)
|
||||||
|
{
|
||||||
|
(SimplificationResult::NotSimplified, SimplificationResult::NotSimplified)
|
||||||
|
=> SimplificationResult::NotSimplified,
|
||||||
|
_ => SimplificationResult::Simplified,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_unnecessary_exists_parameters(formula: &mut foliage::Formula) -> SimplificationResult
|
||||||
|
{
|
||||||
|
use foliage::Formula;
|
||||||
|
|
||||||
|
match formula
|
||||||
|
{
|
||||||
|
Formula::And(ref mut arguments)
|
||||||
|
| Formula::IfAndOnlyIf(ref mut arguments)
|
||||||
|
| Formula::Or(ref mut arguments) =>
|
||||||
|
{
|
||||||
|
let mut simplification_result = SimplificationResult::NotSimplified;
|
||||||
|
|
||||||
|
for argument in arguments
|
||||||
|
{
|
||||||
|
simplification_result = simplification_result.or(
|
||||||
|
remove_unnecessary_exists_parameters(argument));
|
||||||
|
}
|
||||||
|
|
||||||
|
simplification_result
|
||||||
|
},
|
||||||
|
Formula::Boolean(_)
|
||||||
|
| Formula::Compare(_)
|
||||||
|
| Formula::Predicate(_) => SimplificationResult::NotSimplified,
|
||||||
|
Formula::Exists(ref mut quantified_formula) =>
|
||||||
|
{
|
||||||
|
let mut simplification_result =
|
||||||
|
remove_unnecessary_exists_parameters(&mut quantified_formula.argument);
|
||||||
|
|
||||||
|
let arguments = match *quantified_formula.argument
|
||||||
|
{
|
||||||
|
Formula::And(ref mut arguments) => arguments,
|
||||||
|
_ => return remove_unnecessary_exists_parameters(&mut quantified_formula.argument),
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: do not copy parameters, use std::vec::Vec::retain instead
|
||||||
|
quantified_formula.parameters =
|
||||||
|
std::rc::Rc::new(quantified_formula.parameters.iter().filter_map(
|
||||||
|
|parameter|
|
||||||
|
{
|
||||||
|
let assignment = arguments.iter().enumerate().find_map(
|
||||||
|
|(argument_index, argument)|
|
||||||
|
{
|
||||||
|
let (left, right) = match argument
|
||||||
|
{
|
||||||
|
Formula::Compare(foliage::Compare{
|
||||||
|
operator: foliage::ComparisonOperator::Equal, ref left,
|
||||||
|
ref right})
|
||||||
|
=> (left, right),
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let foliage::Term::Variable(ref variable) = **left
|
||||||
|
{
|
||||||
|
if variable.declaration == *parameter
|
||||||
|
&& !crate::term_contains_variable(right, parameter)
|
||||||
|
{
|
||||||
|
// TODO: avoid copy
|
||||||
|
return Some((argument_index, crate::copy_term(right)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some((assignment_index, assigned_term)) = assignment
|
||||||
|
{
|
||||||
|
arguments.remove(assignment_index);
|
||||||
|
|
||||||
|
for argument in arguments.iter_mut()
|
||||||
|
{
|
||||||
|
crate::replace_variable_in_formula_with_term(argument, parameter,
|
||||||
|
&assigned_term);
|
||||||
|
}
|
||||||
|
|
||||||
|
simplification_result = SimplificationResult::Simplified;
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(std::rc::Rc::clone(parameter))
|
||||||
|
})
|
||||||
|
.collect());
|
||||||
|
|
||||||
|
simplification_result
|
||||||
|
}
|
||||||
|
Formula::ForAll(ref mut quantified_formula) =>
|
||||||
|
remove_unnecessary_exists_parameters(&mut quantified_formula.argument),
|
||||||
|
Formula::Implies(ref mut implies) =>
|
||||||
|
remove_unnecessary_exists_parameters(&mut implies.antecedent)
|
||||||
|
.or(remove_unnecessary_exists_parameters(&mut implies.implication)),
|
||||||
|
Formula::Not(ref mut argument) =>
|
||||||
|
remove_unnecessary_exists_parameters(argument),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simplify_quantified_formulas_without_parameters(formula: &mut foliage::Formula)
|
||||||
|
-> SimplificationResult
|
||||||
|
{
|
||||||
|
use foliage::Formula;
|
||||||
|
|
||||||
|
match formula
|
||||||
|
{
|
||||||
|
Formula::And(arguments)
|
||||||
|
| Formula::IfAndOnlyIf(arguments)
|
||||||
|
| Formula::Or(arguments) =>
|
||||||
|
{
|
||||||
|
let mut simplification_result = SimplificationResult::NotSimplified;
|
||||||
|
|
||||||
|
for mut argument in arguments
|
||||||
|
{
|
||||||
|
simplification_result = simplification_result.or(
|
||||||
|
simplify_quantified_formulas_without_parameters(&mut argument));
|
||||||
|
}
|
||||||
|
|
||||||
|
simplification_result
|
||||||
|
},
|
||||||
|
Formula::Boolean(_)
|
||||||
|
| Formula::Compare(_)
|
||||||
|
| Formula::Predicate(_) => SimplificationResult::NotSimplified,
|
||||||
|
Formula::Exists(quantified_formula)
|
||||||
|
| Formula::ForAll(quantified_formula) =>
|
||||||
|
{
|
||||||
|
if quantified_formula.parameters.is_empty()
|
||||||
|
{
|
||||||
|
// TODO: remove workaround
|
||||||
|
let mut argument = foliage::Formula::false_();
|
||||||
|
std::mem::swap(&mut argument, &mut quantified_formula.argument);
|
||||||
|
|
||||||
|
*formula = argument;
|
||||||
|
|
||||||
|
return SimplificationResult::Simplified;
|
||||||
|
}
|
||||||
|
|
||||||
|
simplify_quantified_formulas_without_parameters(&mut quantified_formula.argument)
|
||||||
|
},
|
||||||
|
Formula::Implies(ref mut implies) =>
|
||||||
|
simplify_quantified_formulas_without_parameters(&mut implies.antecedent)
|
||||||
|
.or(simplify_quantified_formulas_without_parameters(&mut implies.implication)),
|
||||||
|
Formula::Not(ref mut argument) =>
|
||||||
|
simplify_quantified_formulas_without_parameters(argument),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simplify_trivial_n_ary_formulas(formula: &mut foliage::Formula) -> SimplificationResult
|
||||||
|
{
|
||||||
|
use foliage::Formula;
|
||||||
|
|
||||||
|
match formula
|
||||||
|
{
|
||||||
|
Formula::And(arguments)
|
||||||
|
| Formula::IfAndOnlyIf(arguments) if arguments.is_empty() =>
|
||||||
|
{
|
||||||
|
*formula = foliage::Formula::true_();
|
||||||
|
|
||||||
|
return SimplificationResult::Simplified;
|
||||||
|
},
|
||||||
|
| Formula::Or(arguments) if arguments.is_empty() =>
|
||||||
|
{
|
||||||
|
*formula = foliage::Formula::false_();
|
||||||
|
|
||||||
|
return SimplificationResult::Simplified;
|
||||||
|
},
|
||||||
|
Formula::And(arguments)
|
||||||
|
| Formula::IfAndOnlyIf(arguments)
|
||||||
|
| Formula::Or(arguments) =>
|
||||||
|
{
|
||||||
|
if arguments.len() == 1
|
||||||
|
{
|
||||||
|
*formula = arguments.remove(0);
|
||||||
|
|
||||||
|
return SimplificationResult::Simplified;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut simplification_result = SimplificationResult::NotSimplified;
|
||||||
|
|
||||||
|
for mut argument in arguments
|
||||||
|
{
|
||||||
|
simplification_result = simplification_result.or(
|
||||||
|
simplify_trivial_n_ary_formulas(&mut argument));
|
||||||
|
}
|
||||||
|
|
||||||
|
simplification_result
|
||||||
|
},
|
||||||
|
Formula::Boolean(_)
|
||||||
|
| Formula::Compare(_)
|
||||||
|
| Formula::Predicate(_) => SimplificationResult::NotSimplified,
|
||||||
|
Formula::Exists(ref mut quantified_formula)
|
||||||
|
| Formula::ForAll(ref mut quantified_formula) =>
|
||||||
|
simplify_trivial_n_ary_formulas(&mut quantified_formula.argument),
|
||||||
|
Formula::Implies(ref mut implies) =>
|
||||||
|
simplify_trivial_n_ary_formulas(&mut implies.antecedent)
|
||||||
|
.or(simplify_trivial_n_ary_formulas(&mut implies.implication)),
|
||||||
|
Formula::Not(ref mut argument) =>
|
||||||
|
simplify_trivial_n_ary_formulas(argument),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn simplify(formula: &mut foliage::Formula)
|
||||||
|
{
|
||||||
|
loop
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -2,11 +2,13 @@ mod arithmetic_terms;
|
|||||||
mod closures;
|
mod closures;
|
||||||
mod copy_formula;
|
mod copy_formula;
|
||||||
mod output_predicates;
|
mod output_predicates;
|
||||||
|
mod variables_in_terms;
|
||||||
|
|
||||||
pub(crate) use arithmetic_terms::*;
|
pub(crate) use arithmetic_terms::*;
|
||||||
pub(crate) use closures::*;
|
pub(crate) use closures::*;
|
||||||
pub(crate) use copy_formula::*;
|
pub(crate) use copy_formula::*;
|
||||||
pub(crate) use output_predicates::*;
|
pub(crate) use output_predicates::*;
|
||||||
|
pub(crate) use variables_in_terms::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
pub(crate) enum OperatorNotation
|
pub(crate) enum OperatorNotation
|
||||||
|
@ -172,7 +172,7 @@ pub(crate) fn replace_variable_in_formula_with_term(formula: &mut foliage::Formu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_term(term: &foliage::Term) -> foliage::Term
|
pub(crate) fn copy_term(term: &foliage::Term) -> foliage::Term
|
||||||
{
|
{
|
||||||
use foliage::Term;
|
use foliage::Term;
|
||||||
|
|
||||||
|
21
src/utils/variables_in_terms.rs
Normal file
21
src/utils/variables_in_terms.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
pub(crate) fn term_contains_variable(term: &foliage::Term,
|
||||||
|
variable_declaration: &foliage::VariableDeclaration)
|
||||||
|
-> bool
|
||||||
|
{
|
||||||
|
use foliage::Term;
|
||||||
|
|
||||||
|
match term
|
||||||
|
{
|
||||||
|
Term::BinaryOperation(binary_operation) =>
|
||||||
|
term_contains_variable(&binary_operation.left, variable_declaration)
|
||||||
|
|| term_contains_variable(&binary_operation.right, variable_declaration),
|
||||||
|
Term::Boolean(_)
|
||||||
|
| Term::Function(_)
|
||||||
|
| Term::Integer(_)
|
||||||
|
| Term::SpecialInteger(_)
|
||||||
|
| Term::String(_) => false,
|
||||||
|
Term::UnaryOperation(unary_operation) =>
|
||||||
|
term_contains_variable(&unary_operation.argument, variable_declaration),
|
||||||
|
Term::Variable(variable) => *variable.declaration == *variable_declaration,
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user