247 lines
6.6 KiB
Rust
247 lines
6.6 KiB
Rust
#[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;
|
||
}
|
||
}
|