Support hiding auxiliary predicates
This commit is contained in:
parent
84031c483b
commit
82422cc28f
@ -1,6 +1,4 @@
|
|||||||
# Auxiliary predicate to determine whether a variable is integer. is_int/1 is declared as an input
|
# Auxiliary predicate to determine whether a variable is integer
|
||||||
# predicate so that anthem doesn’t generate its completed definition
|
|
||||||
input: is_int/1.
|
|
||||||
axiom: forall X (is_int(X) <-> exists N X = N).
|
axiom: forall X (is_int(X) <-> exists N X = N).
|
||||||
|
|
||||||
# Perform the proofs under the assumption that n is a nonnegative integer input constant. n stands
|
# Perform the proofs under the assumption that n is a nonnegative integer input constant. n stands
|
||||||
@ -11,6 +9,10 @@ assume: n >= 0.
|
|||||||
# s/2 is the input predicate defining the sets for which the program searches for exact covers
|
# s/2 is the input predicate defining the sets for which the program searches for exact covers
|
||||||
input: s/2.
|
input: s/2.
|
||||||
|
|
||||||
|
# Only the in/1 predicate is an actual output, s/2 is an input and covered/1 and is_int/1 are
|
||||||
|
# auxiliary
|
||||||
|
output: in/1.
|
||||||
|
|
||||||
# Perform the proofs under the assumption that the second parameter of s/2 (the number of the set)
|
# Perform the proofs under the assumption that the second parameter of s/2 (the number of the set)
|
||||||
# is always an integer
|
# is always an integer
|
||||||
assume: forall X, Y (s(X, Y) -> is_int(Y)).
|
assume: forall X, Y (s(X, Y) -> is_int(Y)).
|
||||||
|
@ -1 +1,3 @@
|
|||||||
|
input: p/2.
|
||||||
|
|
||||||
assert: exists X, Y p(X, Y) <-> exists X q(X).
|
assert: exists X, Y p(X, Y) <-> exists X q(X).
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
input: p/1.
|
||||||
|
|
||||||
assert:
|
assert:
|
||||||
forall N
|
forall N
|
||||||
(
|
(
|
||||||
|
@ -44,6 +44,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match problem.restrict_to_output_predicates()
|
||||||
|
{
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(error) =>
|
||||||
|
{
|
||||||
|
log::error!("could not restrict problem to output predicates: {}", error);
|
||||||
|
std::process::exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match problem.prove(proof_direction)
|
match problem.prove(proof_direction)
|
||||||
{
|
{
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
|
23
src/error.rs
23
src/error.rs
@ -22,6 +22,9 @@ pub enum Kind
|
|||||||
UnknownDomainIdentifier(String),
|
UnknownDomainIdentifier(String),
|
||||||
VariableNameNotAllowed(String),
|
VariableNameNotAllowed(String),
|
||||||
FormulaNotClosed(std::rc::Rc<foliage::VariableDeclarations>),
|
FormulaNotClosed(std::rc::Rc<foliage::VariableDeclarations>),
|
||||||
|
NoCompletedDefinitionFound(std::rc::Rc<foliage::PredicateDeclaration>),
|
||||||
|
CannotHidePredicate(std::rc::Rc<foliage::PredicateDeclaration>,
|
||||||
|
std::rc::Rc<foliage::PredicateDeclaration>),
|
||||||
WriteTPTPProgram,
|
WriteTPTPProgram,
|
||||||
RunVampire,
|
RunVampire,
|
||||||
// TODO: rename to something Vampire-specific
|
// TODO: rename to something Vampire-specific
|
||||||
@ -148,6 +151,21 @@ impl Error
|
|||||||
Self::new(Kind::FormulaNotClosed(free_variables))
|
Self::new(Kind::FormulaNotClosed(free_variables))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn new_no_completed_definition_found(
|
||||||
|
predicate_declaration: std::rc::Rc<foliage::PredicateDeclaration>)
|
||||||
|
-> Self
|
||||||
|
{
|
||||||
|
Self::new(Kind::NoCompletedDefinitionFound(predicate_declaration))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn new_cannot_hide_predicate(
|
||||||
|
predicate_declaration_1: std::rc::Rc<foliage::PredicateDeclaration>,
|
||||||
|
predicate_declaration_2: std::rc::Rc<foliage::PredicateDeclaration>)
|
||||||
|
-> Self
|
||||||
|
{
|
||||||
|
Self::new(Kind::CannotHidePredicate(predicate_declaration_1, predicate_declaration_2))
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn new_write_tptp_program<S: Into<Source>>(source: S) -> Self
|
pub(crate) fn new_write_tptp_program<S: Into<Source>>(source: S) -> Self
|
||||||
{
|
{
|
||||||
Self::new(Kind::WriteTPTPProgram).with(source)
|
Self::new(Kind::WriteTPTPProgram).with(source)
|
||||||
@ -219,6 +237,11 @@ impl std::fmt::Debug for Error
|
|||||||
write!(formatter, "formula may not contain free variables (free variables in this formula: {})",
|
write!(formatter, "formula may not contain free variables (free variables in this formula: {})",
|
||||||
free_variable_names_output)
|
free_variable_names_output)
|
||||||
},
|
},
|
||||||
|
Kind::NoCompletedDefinitionFound(ref predicate_declaration) =>
|
||||||
|
write!(formatter, "no completed definition found for {}", predicate_declaration),
|
||||||
|
Kind::CannotHidePredicate(ref predicate_declaration_1, ref predicate_declaration_2) =>
|
||||||
|
write!(formatter, "cannot hide predicate {} because it depends on {}",
|
||||||
|
predicate_declaration_1, predicate_declaration_2),
|
||||||
Kind::RunVampire => write!(formatter, "could not run Vampire"),
|
Kind::RunVampire => write!(formatter, "could not run Vampire"),
|
||||||
Kind::ProveProgram(exit_code, ref stdout, ref stderr) =>
|
Kind::ProveProgram(exit_code, ref stdout, ref stderr) =>
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
|
#![feature(vec_remove_item)]
|
||||||
|
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
118
src/problem.rs
118
src/problem.rs
@ -20,6 +20,9 @@ type VariableDeclarationIDs
|
|||||||
type InputConstantDeclarationDomains
|
type InputConstantDeclarationDomains
|
||||||
= std::collections::BTreeMap<std::rc::Rc<foliage::FunctionDeclaration>, crate::Domain>;
|
= std::collections::BTreeMap<std::rc::Rc<foliage::FunctionDeclaration>, crate::Domain>;
|
||||||
|
|
||||||
|
type VariableDeclarationDomains
|
||||||
|
= std::collections::BTreeMap<std::rc::Rc<foliage::VariableDeclaration>, crate::Domain>;
|
||||||
|
|
||||||
struct FormatContext<'a, 'b>
|
struct FormatContext<'a, 'b>
|
||||||
{
|
{
|
||||||
pub program_variable_declaration_ids: std::cell::RefCell<VariableDeclarationIDs>,
|
pub program_variable_declaration_ids: std::cell::RefCell<VariableDeclarationIDs>,
|
||||||
@ -28,9 +31,6 @@ struct FormatContext<'a, 'b>
|
|||||||
pub variable_declaration_domains: &'b VariableDeclarationDomains,
|
pub variable_declaration_domains: &'b VariableDeclarationDomains,
|
||||||
}
|
}
|
||||||
|
|
||||||
type VariableDeclarationDomains
|
|
||||||
= std::collections::BTreeMap<std::rc::Rc<foliage::VariableDeclaration>, crate::Domain>;
|
|
||||||
|
|
||||||
pub struct Problem
|
pub struct Problem
|
||||||
{
|
{
|
||||||
function_declarations: std::cell::RefCell<foliage::FunctionDeclarations>,
|
function_declarations: std::cell::RefCell<foliage::FunctionDeclarations>,
|
||||||
@ -82,6 +82,64 @@ impl Problem
|
|||||||
section.push(statement);
|
section.push(statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn restrict_to_output_predicates(&mut self) -> Result<(), crate::Error>
|
||||||
|
{
|
||||||
|
let predicate_declarations = self.predicate_declarations.borrow();
|
||||||
|
let input_predicate_declarations = self.input_predicate_declarations.borrow();
|
||||||
|
let output_predicate_declarations = self.output_predicate_declarations.borrow();
|
||||||
|
|
||||||
|
// If no output statements were provided, show all predicates by default
|
||||||
|
if output_predicate_declarations.is_empty()
|
||||||
|
{
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let hidden_predicate_declarations =
|
||||||
|
predicate_declarations.iter().filter(|x| !output_predicate_declarations.contains(*x)
|
||||||
|
&& !input_predicate_declarations.contains(*x));
|
||||||
|
|
||||||
|
let mut statements = self.statements.borrow_mut();
|
||||||
|
|
||||||
|
for hidden_predicate_declaration in hidden_predicate_declarations
|
||||||
|
{
|
||||||
|
let matches_completed_definition =
|
||||||
|
|(_, statement): &(_, &Statement)| match statement.kind
|
||||||
|
{
|
||||||
|
StatementKind::CompletedDefinition(ref predicate_declaration) =>
|
||||||
|
predicate_declaration == hidden_predicate_declaration,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let completed_definitions = match statements.get_mut(&SectionKind::CompletedDefinitions)
|
||||||
|
{
|
||||||
|
Some(completed_definitions) => completed_definitions,
|
||||||
|
None => return Ok(()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let completed_definition = match completed_definitions.iter().enumerate()
|
||||||
|
.find(matches_completed_definition)
|
||||||
|
{
|
||||||
|
Some((completed_definition_index, _)) =>
|
||||||
|
completed_definitions.remove(completed_definition_index).formula,
|
||||||
|
None => return Err(crate::Error::new_no_completed_definition_found(
|
||||||
|
std::rc::Rc::clone(hidden_predicate_declaration))),
|
||||||
|
};
|
||||||
|
|
||||||
|
drop(completed_definitions);
|
||||||
|
|
||||||
|
for (_, statements) in statements.iter_mut()
|
||||||
|
{
|
||||||
|
for statement in statements.iter_mut()
|
||||||
|
{
|
||||||
|
crate::utils::replace_predicate_in_formula_with_completed_definition(
|
||||||
|
&mut statement.formula, &completed_definition, self)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn print_step_title(&self, step_title: &str, color: &termcolor::ColorSpec)
|
fn print_step_title(&self, step_title: &str, color: &termcolor::ColorSpec)
|
||||||
{
|
{
|
||||||
let longest_possible_key = " Finished";
|
let longest_possible_key = " Finished";
|
||||||
@ -216,17 +274,7 @@ impl Problem
|
|||||||
|
|
||||||
fn prove_unproven_statements(&self) -> Result<ProofResult, crate::Error>
|
fn prove_unproven_statements(&self) -> Result<ProofResult, crate::Error>
|
||||||
{
|
{
|
||||||
let format_context = FormatContext
|
let display_statement = |statement: &Statement|
|
||||||
{
|
|
||||||
program_variable_declaration_ids:
|
|
||||||
std::cell::RefCell::new(VariableDeclarationIDs::new()),
|
|
||||||
integer_variable_declaration_ids:
|
|
||||||
std::cell::RefCell::new(VariableDeclarationIDs::new()),
|
|
||||||
input_constant_declaration_domains: &self.input_constant_declaration_domains.borrow(),
|
|
||||||
variable_declaration_domains: &self.variable_declaration_domains.borrow(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let display_statement = |statement: &Statement, format_context|
|
|
||||||
{
|
{
|
||||||
let step_title = match statement.proof_status
|
let step_title = match statement.proof_status
|
||||||
{
|
{
|
||||||
@ -256,15 +304,17 @@ impl Problem
|
|||||||
self.shell.borrow_mut().print(&format!("{}: ", statement.kind),
|
self.shell.borrow_mut().print(&format!("{}: ", statement.kind),
|
||||||
&termcolor::ColorSpec::new());
|
&termcolor::ColorSpec::new());
|
||||||
|
|
||||||
match statement.kind
|
let format_context = FormatContext
|
||||||
{
|
{
|
||||||
StatementKind::CompletedDefinition(_)
|
program_variable_declaration_ids:
|
||||||
| StatementKind::IntegrityConstraint =>
|
std::cell::RefCell::new(VariableDeclarationIDs::new()),
|
||||||
print!("{}",
|
integer_variable_declaration_ids:
|
||||||
foliage::format::display_formula(&statement.formula, format_context)),
|
std::cell::RefCell::new(VariableDeclarationIDs::new()),
|
||||||
_ =>
|
input_constant_declaration_domains: &self.input_constant_declaration_domains.borrow(),
|
||||||
print!("{}", statement.formula),
|
variable_declaration_domains: &self.variable_declaration_domains.borrow(),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
print!("{}", foliage::format::display_formula(&statement.formula, &format_context));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Show all statements that are assumed to be proven
|
// Show all statements that are assumed to be proven
|
||||||
@ -273,7 +323,7 @@ impl Problem
|
|||||||
for statement in statements.iter_mut()
|
for statement in statements.iter_mut()
|
||||||
.filter(|statement| statement.proof_status == ProofStatus::AssumedProven)
|
.filter(|statement| statement.proof_status == ProofStatus::AssumedProven)
|
||||||
{
|
{
|
||||||
display_statement(statement, &format_context);
|
display_statement(statement);
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,7 +336,7 @@ impl Problem
|
|||||||
statement.proof_status = ProofStatus::ToProveNow;
|
statement.proof_status = ProofStatus::ToProveNow;
|
||||||
|
|
||||||
print!("\x1b[s");
|
print!("\x1b[s");
|
||||||
display_statement(statement, &format_context);
|
display_statement(statement);
|
||||||
print!("\x1b[u");
|
print!("\x1b[u");
|
||||||
|
|
||||||
use std::io::Write as _;
|
use std::io::Write as _;
|
||||||
@ -309,7 +359,7 @@ impl Problem
|
|||||||
// TODO: make configurable again
|
// TODO: make configurable again
|
||||||
let (proof_result, proof_time_seconds) =
|
let (proof_result, proof_time_seconds) =
|
||||||
run_vampire(&tptp_problem_to_prove_next_statement,
|
run_vampire(&tptp_problem_to_prove_next_statement,
|
||||||
Some(&["--mode", "casc", "--cores", "8", "--time_limit", "15"]))?;
|
Some(&["--mode", "casc", "--cores", "8", "--time_limit", "300"]))?;
|
||||||
|
|
||||||
match self.next_unproven_statement_do_mut(
|
match self.next_unproven_statement_do_mut(
|
||||||
|statement|
|
|statement|
|
||||||
@ -323,7 +373,7 @@ impl Problem
|
|||||||
|
|
||||||
self.shell.borrow_mut().erase_line();
|
self.shell.borrow_mut().erase_line();
|
||||||
|
|
||||||
display_statement(statement, &format_context);
|
display_statement(statement);
|
||||||
|
|
||||||
match proof_result
|
match proof_result
|
||||||
{
|
{
|
||||||
@ -591,6 +641,22 @@ impl crate::traits::AssignVariableDeclarationDomain for Problem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl crate::traits::VariableDeclarationDomain for Problem
|
||||||
|
{
|
||||||
|
fn variable_declaration_domain(&self,
|
||||||
|
variable_declaration: &std::rc::Rc<foliage::VariableDeclaration>)
|
||||||
|
-> Option<crate::Domain>
|
||||||
|
{
|
||||||
|
self.variable_declaration_domains.borrow().iter().find_map(
|
||||||
|
|(x, domain)|
|
||||||
|
match x == variable_declaration
|
||||||
|
{
|
||||||
|
true => Some(*domain),
|
||||||
|
false => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'b> FormatContext<'a, 'b>
|
impl<'a, 'b> FormatContext<'a, 'b>
|
||||||
{
|
{
|
||||||
fn variable_declaration_id(&self,
|
fn variable_declaration_id(&self,
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
mod arithmetic_terms;
|
mod arithmetic_terms;
|
||||||
mod closures;
|
mod closures;
|
||||||
|
mod copy_formula;
|
||||||
|
mod output_predicates;
|
||||||
|
|
||||||
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 output_predicates::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
pub(crate) enum OperatorNotation
|
pub(crate) enum OperatorNotation
|
||||||
|
262
src/utils/copy_formula.rs
Normal file
262
src/utils/copy_formula.rs
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
fn replace_variables_in_term(term: &mut foliage::Term,
|
||||||
|
old_variable_declarations: &foliage::VariableDeclarations,
|
||||||
|
new_variable_declarations: &foliage::VariableDeclarations)
|
||||||
|
{
|
||||||
|
assert_eq!(old_variable_declarations.len(), new_variable_declarations.len());
|
||||||
|
|
||||||
|
use foliage::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 foliage::Formula,
|
||||||
|
old_variable_declarations: &foliage::VariableDeclarations,
|
||||||
|
new_variable_declarations: &foliage::VariableDeclarations)
|
||||||
|
{
|
||||||
|
use foliage::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 foliage::Term,
|
||||||
|
variable_declaration: &foliage::VariableDeclaration, replacement_term: &foliage::Term)
|
||||||
|
{
|
||||||
|
use foliage::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 foliage::Formula,
|
||||||
|
variable_declaration: &foliage::VariableDeclaration, replacement_term: &foliage::Term)
|
||||||
|
{
|
||||||
|
use foliage::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(_) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy_term(term: &foliage::Term) -> foliage::Term
|
||||||
|
{
|
||||||
|
use foliage::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<D>(quantified_expression: &foliage::QuantifiedFormula, declarations: &D)
|
||||||
|
-> foliage::QuantifiedFormula
|
||||||
|
where
|
||||||
|
D: crate::traits::VariableDeclarationDomain + crate::traits::AssignVariableDeclarationDomain,
|
||||||
|
{
|
||||||
|
let copy_parameters =
|
||||||
|
quantified_expression.parameters.iter()
|
||||||
|
.map(
|
||||||
|
|parameter|
|
||||||
|
{
|
||||||
|
let copy_parameter = std::rc::Rc::new(
|
||||||
|
foliage::VariableDeclaration::new(parameter.name.clone()));
|
||||||
|
|
||||||
|
if let Some(domain) = declarations.variable_declaration_domain(parameter)
|
||||||
|
{
|
||||||
|
declarations.assign_variable_declaration_domain(©_parameter, domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_parameter
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let copy_parameters = std::rc::Rc::new(copy_parameters);
|
||||||
|
|
||||||
|
let mut copy_argument = copy_formula(&quantified_expression.argument, declarations);
|
||||||
|
|
||||||
|
replace_variables_in_formula(&mut copy_argument, &quantified_expression.parameters,
|
||||||
|
©_parameters);
|
||||||
|
|
||||||
|
foliage::QuantifiedFormula::new(copy_parameters, Box::new(copy_argument))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn copy_formula<D>(formula: &foliage::Formula, declarations: &D) -> foliage::Formula
|
||||||
|
where
|
||||||
|
D: crate::traits::VariableDeclarationDomain + crate::traits::AssignVariableDeclarationDomain,
|
||||||
|
{
|
||||||
|
use foliage::Formula;
|
||||||
|
|
||||||
|
match formula
|
||||||
|
{
|
||||||
|
Formula::And(arguments) =>
|
||||||
|
Formula::and(arguments.iter().map(
|
||||||
|
|argument| copy_formula(argument, declarations)).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, declarations)),
|
||||||
|
Formula::ForAll(quantified_formula) =>
|
||||||
|
Formula::ForAll(copy_quantified_formula(quantified_formula, declarations)),
|
||||||
|
Formula::IfAndOnlyIf(arguments) =>
|
||||||
|
Formula::if_and_only_if(
|
||||||
|
arguments.iter().map(|argument| copy_formula(argument, declarations)).collect()),
|
||||||
|
Formula::Implies(implies) =>
|
||||||
|
Formula::implies(implies.direction,
|
||||||
|
Box::new(copy_formula(&implies.antecedent, declarations)),
|
||||||
|
Box::new(copy_formula(&implies.implication, declarations))),
|
||||||
|
Formula::Not(argument) => Formula::not(Box::new(copy_formula(&argument, declarations))),
|
||||||
|
Formula::Or(arguments) =>
|
||||||
|
Formula::or(arguments.iter().map(
|
||||||
|
|argument| copy_formula(argument, declarations)).collect()),
|
||||||
|
Formula::Predicate(predicate) =>
|
||||||
|
Formula::predicate(std::rc::Rc::clone(&predicate.declaration),
|
||||||
|
predicate.arguments.iter().map(|argument| copy_term(argument)).collect()),
|
||||||
|
}
|
||||||
|
}
|
127
src/utils/output_predicates.rs
Normal file
127
src/utils/output_predicates.rs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
fn formula_contains_predicate(formula: &foliage::Formula,
|
||||||
|
predicate_declaration: &foliage::PredicateDeclaration)
|
||||||
|
-> bool
|
||||||
|
{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn replace_predicate_in_formula<D>(formula: &mut foliage::Formula,
|
||||||
|
predicate_to_replace: &foliage::Predicate, replacement_formula: &foliage::Formula,
|
||||||
|
declarations: &D)
|
||||||
|
where
|
||||||
|
D: crate::traits::VariableDeclarationDomain + crate::traits::AssignVariableDeclarationDomain,
|
||||||
|
{
|
||||||
|
use foliage::{Formula, Term};
|
||||||
|
|
||||||
|
match formula
|
||||||
|
{
|
||||||
|
Formula::And(arguments)
|
||||||
|
| Formula::IfAndOnlyIf(arguments)
|
||||||
|
| Formula::Or(arguments) =>
|
||||||
|
for mut argument in arguments
|
||||||
|
{
|
||||||
|
replace_predicate_in_formula(&mut argument, predicate_to_replace,
|
||||||
|
replacement_formula, declarations);
|
||||||
|
},
|
||||||
|
Formula::Boolean(_)
|
||||||
|
| Formula::Compare(_) => (),
|
||||||
|
Formula::Exists(quantified_expression)
|
||||||
|
| Formula::ForAll(quantified_expression) =>
|
||||||
|
replace_predicate_in_formula(&mut quantified_expression.argument, predicate_to_replace,
|
||||||
|
replacement_formula, declarations),
|
||||||
|
Formula::Implies(implies) =>
|
||||||
|
{
|
||||||
|
replace_predicate_in_formula(&mut implies.antecedent, predicate_to_replace,
|
||||||
|
replacement_formula, declarations);
|
||||||
|
replace_predicate_in_formula(&mut implies.implication, predicate_to_replace,
|
||||||
|
replacement_formula, declarations);
|
||||||
|
},
|
||||||
|
Formula::Not(argument) =>
|
||||||
|
replace_predicate_in_formula(argument, predicate_to_replace, replacement_formula,
|
||||||
|
declarations),
|
||||||
|
Formula::Predicate(predicate) =>
|
||||||
|
if predicate.declaration == predicate_to_replace.declaration
|
||||||
|
{
|
||||||
|
let mut replacement_formula =
|
||||||
|
crate::utils::copy_formula(replacement_formula, declarations);
|
||||||
|
|
||||||
|
for (index, argument) in predicate.arguments.iter().enumerate()
|
||||||
|
{
|
||||||
|
let variable_declaration = match &predicate_to_replace.arguments[index]
|
||||||
|
{
|
||||||
|
Term::Variable(variable) => &variable.declaration,
|
||||||
|
_ => panic!("invalid completed definition"),
|
||||||
|
};
|
||||||
|
|
||||||
|
crate::utils::replace_variable_in_formula_with_term(&mut replacement_formula,
|
||||||
|
&variable_declaration, argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
*formula = replacement_formula;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn replace_predicate_in_formula_with_completed_definition<D>(
|
||||||
|
formula: &mut foliage::Formula, completed_definition: &foliage::Formula, declarations: &D)
|
||||||
|
-> Result<(), crate::Error>
|
||||||
|
where
|
||||||
|
D: crate::traits::VariableDeclarationDomain + crate::traits::AssignVariableDeclarationDomain,
|
||||||
|
{
|
||||||
|
let false_ = foliage::Formula::false_();
|
||||||
|
|
||||||
|
// TODO: refactor
|
||||||
|
let (completed_definition_predicate, completed_definition) = match completed_definition
|
||||||
|
{
|
||||||
|
foliage::Formula::ForAll(quantified_expression) => match *quantified_expression.argument
|
||||||
|
{
|
||||||
|
foliage::Formula::IfAndOnlyIf(ref arguments) =>
|
||||||
|
{
|
||||||
|
assert_eq!(arguments.len(), 2, "invalid completed definition");
|
||||||
|
|
||||||
|
match arguments[0]
|
||||||
|
{
|
||||||
|
foliage::Formula::Predicate(ref predicate) => (predicate, &arguments[1]),
|
||||||
|
_ => panic!("invalid completed definition"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
foliage::Formula::Not(ref argument) => match **argument
|
||||||
|
{
|
||||||
|
foliage::Formula::Predicate(ref predicate) => (predicate, &false_),
|
||||||
|
_ => panic!("invalid completed definition"),
|
||||||
|
},
|
||||||
|
_ => panic!("invalid completed definition"),
|
||||||
|
},
|
||||||
|
foliage::Formula::IfAndOnlyIf(ref arguments) =>
|
||||||
|
{
|
||||||
|
assert_eq!(arguments.len(), 2, "invalid completed definition");
|
||||||
|
|
||||||
|
match arguments[0]
|
||||||
|
{
|
||||||
|
foliage::Formula::Predicate(ref predicate) => (predicate, &arguments[1]),
|
||||||
|
_ => panic!("invalid completed definition"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
foliage::Formula::Not(ref argument) => match **argument
|
||||||
|
{
|
||||||
|
foliage::Formula::Predicate(ref predicate) => (predicate, &false_),
|
||||||
|
_ => panic!("invalid completed definition"),
|
||||||
|
},
|
||||||
|
_ => panic!("invalid completed definition"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Predicates can only be substituted by their completed definitions if there is no cycle.
|
||||||
|
// For example, if the completed definition of p/1 references q/1 and vice versa, neither can
|
||||||
|
// be replaced with the completed definition of the other
|
||||||
|
/*if formula_contains_predicate(completed_definition, predicate_declaration)
|
||||||
|
{
|
||||||
|
return Err(crate::Error::new())
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// TODO: detect cycles and warn accordingly
|
||||||
|
|
||||||
|
replace_predicate_in_formula(formula, completed_definition_predicate, completed_definition,
|
||||||
|
declarations);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user