anthem-rs/src/utils/copy_formula.rs
Patrick Lühne 81ddfd450a
Use custom foliage flavor
With this patch, properties specific to variable, function, and
predicate declarations are directly stored within those objects rather
than external maps that need to be queried via traits. This greatly
simplifies many parts of the logic.

This is made possible by implementing a custom foliage flavor, which
makes it possible to swap the built-in declaration types for extended
versions of those types that fulfill certain requirements.
2020-05-22 02:25:00 +02:00

245 lines
8.1 KiB
Rust

fn replace_variables_in_term(term: &mut crate::Term,
old_variable_declarations: &crate::VariableDeclarations,
new_variable_declarations: &crate::VariableDeclarations)
{
assert_eq!(old_variable_declarations.len(), new_variable_declarations.len());
use crate::Term;
match term
{
Term::BinaryOperation(binary_operation) =>
{
replace_variables_in_term(&mut binary_operation.left, old_variable_declarations,
new_variable_declarations);
replace_variables_in_term(&mut binary_operation.right, old_variable_declarations,
new_variable_declarations);
},
Term::Function(function) =>
for mut argument in &mut function.arguments
{
replace_variables_in_term(&mut argument, old_variable_declarations,
new_variable_declarations);
},
Term::UnaryOperation(unary_operation) =>
replace_variables_in_term(&mut unary_operation.argument, old_variable_declarations,
new_variable_declarations),
Term::Variable(variable) =>
if let Some(index) = old_variable_declarations.iter().enumerate()
.find_map(
|(index, variable_declaration)|
{
match *variable_declaration == variable.declaration
{
true => Some(index),
false => None,
}
})
{
variable.declaration = std::rc::Rc::clone(&new_variable_declarations[index]);
},
Term::Boolean(_)
| Term::Integer(_)
| Term::SpecialInteger(_)
| Term::String(_) => (),
}
}
fn replace_variables_in_formula(formula: &mut crate::Formula,
old_variable_declarations: &crate::VariableDeclarations,
new_variable_declarations: &crate::VariableDeclarations)
{
use crate::Formula;
match formula
{
Formula::And(arguments)
| Formula::IfAndOnlyIf(arguments)
| Formula::Or(arguments) =>
for argument in arguments
{
replace_variables_in_formula(argument, old_variable_declarations,
new_variable_declarations);
},
Formula::Compare(compare) =>
{
replace_variables_in_term(&mut compare.left, old_variable_declarations,
new_variable_declarations);
replace_variables_in_term(&mut compare.right, old_variable_declarations,
new_variable_declarations);
},
Formula::Exists(quantified_formula)
| Formula::ForAll(quantified_formula) =>
replace_variables_in_formula(&mut quantified_formula.argument,
old_variable_declarations, new_variable_declarations),
Formula::Implies(implies) =>
{
replace_variables_in_formula(&mut implies.antecedent, old_variable_declarations,
new_variable_declarations);
replace_variables_in_formula(&mut implies.implication, old_variable_declarations,
new_variable_declarations);
},
Formula::Not(argument) =>
replace_variables_in_formula(argument, old_variable_declarations,
new_variable_declarations),
Formula::Predicate(predicate) =>
for mut argument in &mut predicate.arguments
{
replace_variables_in_term(&mut argument, old_variable_declarations,
new_variable_declarations);
},
Formula::Boolean(_) => (),
}
}
fn replace_variable_in_term_with_term(term: &mut crate::Term,
variable_declaration: &crate::VariableDeclaration, replacement_term: &crate::Term)
{
use crate::Term;
match term
{
Term::BinaryOperation(binary_operation) =>
{
replace_variable_in_term_with_term(&mut binary_operation.left, variable_declaration,
replacement_term);
replace_variable_in_term_with_term(&mut binary_operation.right, variable_declaration,
replacement_term);
},
Term::Function(function) =>
for mut argument in &mut function.arguments
{
replace_variable_in_term_with_term(&mut argument, variable_declaration,
replacement_term);
},
Term::UnaryOperation(unary_operation) =>
replace_variable_in_term_with_term(&mut unary_operation.argument, variable_declaration,
replacement_term),
Term::Variable(variable) =>
if *variable.declaration == *variable_declaration
{
*term = copy_term(replacement_term);
},
Term::Boolean(_)
| Term::Integer(_)
| Term::SpecialInteger(_)
| Term::String(_) => (),
}
}
pub(crate) fn replace_variable_in_formula_with_term(formula: &mut crate::Formula,
variable_declaration: &crate::VariableDeclaration, replacement_term: &crate::Term)
{
use crate::Formula;
match formula
{
Formula::And(arguments)
| Formula::IfAndOnlyIf(arguments)
| Formula::Or(arguments) =>
for argument in arguments
{
replace_variable_in_formula_with_term(argument, variable_declaration,
replacement_term);
},
Formula::Compare(compare) =>
{
replace_variable_in_term_with_term(&mut compare.left, variable_declaration,
replacement_term);
replace_variable_in_term_with_term(&mut compare.right, variable_declaration,
replacement_term);
},
Formula::Exists(quantified_formula)
| Formula::ForAll(quantified_formula) =>
replace_variable_in_formula_with_term(&mut quantified_formula.argument,
variable_declaration, replacement_term),
Formula::Implies(implies) =>
{
replace_variable_in_formula_with_term(&mut implies.antecedent, variable_declaration,
replacement_term);
replace_variable_in_formula_with_term(&mut implies.implication, variable_declaration,
replacement_term);
},
Formula::Not(argument) =>
replace_variable_in_formula_with_term(argument, variable_declaration, replacement_term),
Formula::Predicate(predicate) =>
for mut argument in &mut predicate.arguments
{
replace_variable_in_term_with_term(&mut argument, variable_declaration,
replacement_term);
},
Formula::Boolean(_) => (),
}
}
pub(crate) fn copy_term(term: &crate::Term) -> crate::Term
{
use crate::Term;
match term
{
Term::BinaryOperation(binary_operation) =>
Term::binary_operation(binary_operation.operator,
Box::new(copy_term(&binary_operation.left)),
Box::new(copy_term(&binary_operation.right))),
Term::Boolean(value) => Term::boolean(*value),
Term::Function(function) => Term::function(std::rc::Rc::clone(&function.declaration),
function.arguments.iter().map(|argument| copy_term(argument)).collect()),
Term::Integer(value) => Term::integer(*value),
Term::SpecialInteger(value) => Term::special_integer(*value),
Term::String(value) => Term::string(value.clone()),
Term::UnaryOperation(unary_operation) => Term::unary_operation(unary_operation.operator,
Box::new(copy_term(&unary_operation.argument))),
Term::Variable(variable) => Term::variable(std::rc::Rc::clone(&variable.declaration)),
}
}
fn copy_quantified_formula(quantified_expression: &crate::QuantifiedFormula)
-> crate::QuantifiedFormula
{
let copy_parameters =
quantified_expression.parameters.iter()
// TODO: check correctness of clone implementation
.map(|x| x.clone())
.collect();
let copy_parameters = std::rc::Rc::new(copy_parameters);
let mut copy_argument = copy_formula(&quantified_expression.argument);
replace_variables_in_formula(&mut copy_argument, &quantified_expression.parameters,
&copy_parameters);
crate::QuantifiedFormula::new(copy_parameters, Box::new(copy_argument))
}
pub(crate) fn copy_formula(formula: &crate::Formula) -> crate::Formula
{
use crate::Formula;
match formula
{
Formula::And(arguments) =>
Formula::and(arguments.iter().map(|argument| copy_formula(argument)).collect()),
Formula::Boolean(value) => Formula::boolean(*value),
Formula::Compare(compare) =>
Formula::compare(compare.operator, Box::new(copy_term(&compare.left)),
Box::new(copy_term(&compare.right))),
Formula::Exists(quantified_formula) =>
Formula::Exists(copy_quantified_formula(quantified_formula)),
Formula::ForAll(quantified_formula) =>
Formula::ForAll(copy_quantified_formula(quantified_formula)),
Formula::IfAndOnlyIf(arguments) =>
Formula::if_and_only_if(
arguments.iter().map(|argument| copy_formula(argument)).collect()),
Formula::Implies(implies) =>
Formula::implies(implies.direction, Box::new(copy_formula(&implies.antecedent)),
Box::new(copy_formula(&implies.implication))),
Formula::Not(argument) => Formula::not(Box::new(copy_formula(&argument))),
Formula::Or(arguments) =>
Formula::or(arguments.iter().map(|argument| copy_formula(argument)).collect()),
Formula::Predicate(predicate) =>
Formula::predicate(std::rc::Rc::clone(&predicate.declaration),
predicate.arguments.iter().map(|argument| copy_term(argument)).collect()),
}
}