Implement backward proofs

This commit is contained in:
Patrick Lühne 2019-11-06 12:52:08 -06:00
parent bce9d8061c
commit 7da722aeec
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
3 changed files with 119 additions and 79 deletions

View File

@ -1,9 +1,28 @@
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum ProofDirection
{
Forward,
Backward,
}
pub trait DisplayTPTP<'a, DisplayType> pub trait DisplayTPTP<'a, DisplayType>
where DisplayType: 'a + std::fmt::Debug + std::fmt::Display where DisplayType: 'a + std::fmt::Debug + std::fmt::Display
{ {
fn display_tptp(&'a self) -> DisplayType; fn display_tptp(&'a self) -> DisplayType;
} }
pub fn is_statement_kind_conjecture(statement_kind: crate::project::StatementKind,
proof_direction: ProofDirection) -> bool
{
match proof_direction
{
ProofDirection::Forward =>
statement_kind == crate::project::StatementKind::Assertion,
ProofDirection::Backward =>
statement_kind == crate::project::StatementKind::Completion,
}
}
fn is_arithmetic_term(term: &foliage::Term) -> bool fn is_arithmetic_term(term: &foliage::Term) -> bool
{ {
match term match term
@ -221,11 +240,16 @@ struct VariableDeclarationDisplay<'a>(&'a foliage::VariableDeclaration);
struct PredicateDeclarationDisplay<'a>(&'a foliage::PredicateDeclaration); struct PredicateDeclarationDisplay<'a>(&'a foliage::PredicateDeclaration);
struct TermDisplay<'a>(&'a foliage::Term); struct TermDisplay<'a>(&'a foliage::Term);
struct FormulaDisplay<'a>(&'a foliage::Formula); struct FormulaDisplay<'a>(&'a foliage::Formula);
struct StatementKindDisplay<'a>(&'a crate::project::StatementKind); struct StatementKindDisplay
{
statement_kind: crate::project::StatementKind,
proof_direction: ProofDirection,
}
pub struct ProjectDisplay<'a> pub struct ProjectDisplay<'a>
{ {
project: &'a crate::project::Project, project: &'a crate::project::Project,
conjecture: &'a crate::project::Statement, conjecture: &'a crate::project::Statement,
proof_direction: ProofDirection,
} }
impl<'a> DisplayTPTP<'a, VariableDeclarationDisplay<'a>> for foliage::VariableDeclaration impl<'a> DisplayTPTP<'a, VariableDeclarationDisplay<'a>> for foliage::VariableDeclaration
@ -260,21 +284,26 @@ impl<'a> DisplayTPTP<'a, FormulaDisplay<'a>> for foliage::Formula
} }
} }
impl<'a> DisplayTPTP<'a, StatementKindDisplay<'a>> for crate::project::StatementKind fn display_statement_kind_tptp(statement_kind: crate::project::StatementKind,
proof_direction: ProofDirection)
-> StatementKindDisplay
{ {
fn display_tptp(&'a self) -> StatementKindDisplay<'a> StatementKindDisplay
{ {
StatementKindDisplay(self) statement_kind,
proof_direction,
} }
} }
pub fn display_project_with_conjecture_tptp<'a>(project: &'a crate::Project, pub fn display_project_with_conjecture_tptp<'a>(project: &'a crate::Project,
conjecture: &'a crate::project::Statement) -> ProjectDisplay<'a> conjecture: &'a crate::project::Statement, proof_direction: ProofDirection)
-> ProjectDisplay<'a>
{ {
ProjectDisplay ProjectDisplay
{ {
project, project,
conjecture, conjecture,
proof_direction,
} }
} }
@ -548,21 +577,23 @@ impl<'a> std::fmt::Display for FormulaDisplay<'a>
} }
} }
impl<'a> std::fmt::Debug for StatementKindDisplay<'a> impl std::fmt::Debug for StatementKindDisplay
{ {
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{ {
match &self.0 match (self.statement_kind, self.proof_direction)
{ {
crate::project::StatementKind::Axiom => write!(format, "axiom, axiom"), (crate::project::StatementKind::Axiom, _) => write!(format, "axiom, axiom"),
crate::project::StatementKind::Completion => write!(format, "completion, axiom"), (crate::project::StatementKind::Assumption, _) => write!(format, "assumption, axiom"),
crate::project::StatementKind::Assumption => write!(format, "assumption, axiom"), (crate::project::StatementKind::Completion, ProofDirection::Forward) => write!(format, "completion, axiom"),
crate::project::StatementKind::Assertion => write!(format, "assertion, conjecture"), (crate::project::StatementKind::Completion, ProofDirection::Backward) => write!(format, "completion, conjecture"),
(crate::project::StatementKind::Assertion, ProofDirection::Forward) => write!(format, "assertion, conjecture"),
(crate::project::StatementKind::Assertion, ProofDirection::Backward) => write!(format, "assertion, axiom"),
} }
} }
} }
impl<'a> std::fmt::Display for StatementKindDisplay<'a> impl std::fmt::Display for StatementKindDisplay
{ {
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{ {
@ -616,34 +647,25 @@ impl<'a> std::fmt::Debug for ProjectDisplay<'a>
{ {
crate::project::Block::Whitespace(_) => None, crate::project::Block::Whitespace(_) => None,
crate::project::Block::Statement(ref statement) => crate::project::Block::Statement(ref statement) =>
match statement.kind match is_statement_kind_conjecture(statement.kind, self.proof_direction)
{ {
crate::project::StatementKind::Axiom false => Some(statement),
| crate::project::StatementKind::Completion true => None,
| crate::project::StatementKind::Assumption => Some(statement),
crate::project::StatementKind::Assertion => None,
} }
}); });
for axiom in axioms for axiom in axioms
{ {
write!(format, "\ntff({:?}, {:?}).", axiom.kind.display_tptp(), axiom.formula.display_tptp())?; write!(format, "\ntff({:?}, {:?}).",
display_statement_kind_tptp(axiom.kind, self.proof_direction), axiom.formula.display_tptp())?;
} }
match self.conjecture.kind
{
crate::project::StatementKind::Assertion =>
{
write_title(format, "\n\n", "assertion")?; write_title(format, "\n\n", "assertion")?;
write!(format, "\ntff({:?}, {:?}).", crate::project::StatementKind::Assertion.display_tptp(), self.conjecture.formula.display_tptp())?; write!(format, "\ntff({:?}, {:?}).",
display_statement_kind_tptp(self.conjecture.kind, self.proof_direction), self.conjecture.formula.display_tptp())?;
Ok(()) Ok(())
},
crate::project::StatementKind::Axiom => panic!("unexpected axiom statement"),
crate::project::StatementKind::Completion => panic!("unexpected completion statement"),
crate::project::StatementKind::Assumption => panic!("unexpected assumption statement"),
}
} }
} }

View File

@ -19,13 +19,15 @@ fn backup_file_path(file_path: &std::path::Path) -> Result<std::path::PathBuf, a
} }
} }
fn find_conjecture<'a>(project: &'a ask_dracula::Project) -> Option<&'a ask_dracula::project::Statement> fn find_conjecture<'a>(project: &'a ask_dracula::Project,
proof_direction: ask_dracula::format_tptp::ProofDirection)
-> Option<&'a ask_dracula::project::Statement>
{ {
for block in &project.blocks for block in &project.blocks
{ {
if let ask_dracula::project::Block::Statement(ref statement) = block if let ask_dracula::project::Block::Statement(ref statement) = block
{ {
if statement.kind == ask_dracula::project::StatementKind::Assertion if ask_dracula::format_tptp::is_statement_kind_conjecture(statement.kind, proof_direction)
{ {
return Some(statement) return Some(statement)
} }
@ -35,13 +37,15 @@ fn find_conjecture<'a>(project: &'a ask_dracula::Project) -> Option<&'a ask_drac
None None
} }
fn find_conjecture_mut<'a>(project: &'a mut ask_dracula::Project) -> Option<&'a mut ask_dracula::project::Statement> fn find_conjecture_mut<'a>(project: &'a mut ask_dracula::Project,
proof_direction: ask_dracula::format_tptp::ProofDirection)
-> Option<&'a mut ask_dracula::project::Statement>
{ {
for block in &mut project.blocks for block in &mut project.blocks
{ {
if let ask_dracula::project::Block::Statement(ref mut statement) = block if let ask_dracula::project::Block::Statement(ref mut statement) = block
{ {
if statement.kind == ask_dracula::project::StatementKind::Assertion if ask_dracula::format_tptp::is_statement_kind_conjecture(statement.kind, proof_direction)
{ {
return Some(statement) return Some(statement)
} }
@ -123,6 +127,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
{ {
let matches = clap::App::new("Ask Dracula: Using Vampire as an interactive theorem prover") let matches = clap::App::new("Ask Dracula: Using Vampire as an interactive theorem prover")
.arg(clap::Arg::with_name("file").takes_value(true).required(true)) .arg(clap::Arg::with_name("file").takes_value(true).required(true))
.arg(clap::Arg::with_name("proof-direction").long("proof-direction").takes_value(true).default_value("forward"))
.arg(clap::Arg::with_name("vampire_arguments").multiple(true)) .arg(clap::Arg::with_name("vampire_arguments").multiple(true))
.after_help("example: ask_dracula <project file> -- --mode casc --cores 8") .after_help("example: ask_dracula <project file> -- --mode casc --cores 8")
.get_matches(); .get_matches();
@ -136,9 +141,19 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
let replace_statement_kind_regex = regex::Regex::new(r"(assertion)").unwrap(); let replace_statement_kind_regex = regex::Regex::new(r"(assertion)").unwrap();
let proof_directions = match matches.value_of("proof-direction").unwrap()
{
"forward" => vec![ask_dracula::format_tptp::ProofDirection::Forward],
"backward" => vec![ask_dracula::format_tptp::ProofDirection::Backward],
"both" => vec![ask_dracula::format_tptp::ProofDirection::Forward, ask_dracula::format_tptp::ProofDirection::Backward],
proof_direction => panic!("unrecognized proof direction “{}", proof_direction),
};
for proof_direction in proof_directions
{
loop loop
{ {
let conjecture = find_conjecture(&project); let conjecture = find_conjecture(&project, proof_direction);
let vampire_result = match conjecture let vampire_result = match conjecture
{ {
@ -151,13 +166,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
{ {
eprintln!("verifying assertion: {}", conjecture.formula); eprintln!("verifying assertion: {}", conjecture.formula);
let tptp_content = format!("{}", ask_dracula::format_tptp::display_project_with_conjecture_tptp(&project, conjecture)); let tptp_content = format!("{}", ask_dracula::format_tptp::display_project_with_conjecture_tptp(&project, conjecture, proof_direction));
run_vampire(&tptp_content, matches.values_of("vampire_arguments").map(|value| value))? run_vampire(&tptp_content, matches.values_of("vampire_arguments").map(|value| value))?
}, },
}; };
let conjecture = find_conjecture_mut(&mut project).unwrap(); let conjecture = find_conjecture_mut(&mut project, proof_direction).unwrap();
match vampire_result match vampire_result
{ {
@ -192,3 +207,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>>
} }
} }
} }
Ok(())
}

View File

@ -1,4 +1,4 @@
#[derive(Clone, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum StatementKind pub enum StatementKind
{ {
Axiom, Axiom,