Support choice rules with single atom in head

This commit is contained in:
Patrick Lühne 2020-02-02 03:56:34 +01:00
parent 23641987bc
commit 28a804409c
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
1 changed files with 59 additions and 13 deletions

View File

@ -18,6 +18,9 @@ struct Definitions
struct Context struct Context
{ {
pub definitions: std::collections::BTreeMap::<std::rc::Rc<foliage::PredicateDeclaration>, Definitions>,
pub integrity_constraints: foliage::Formulas,
pub function_declarations: foliage::FunctionDeclarations, pub function_declarations: foliage::FunctionDeclarations,
pub predicate_declarations: foliage::PredicateDeclarations, pub predicate_declarations: foliage::PredicateDeclarations,
pub variable_declaration_stack: foliage::VariableDeclarationStack, pub variable_declaration_stack: foliage::VariableDeclarationStack,
@ -29,6 +32,8 @@ impl Context
{ {
Self Self
{ {
definitions: std::collections::BTreeMap::<_, _>::new(),
integrity_constraints: vec![],
function_declarations: foliage::FunctionDeclarations::new(), function_declarations: foliage::FunctionDeclarations::new(),
predicate_declarations: foliage::PredicateDeclarations::new(), predicate_declarations: foliage::PredicateDeclarations::new(),
variable_declaration_stack: foliage::VariableDeclarationStack::new(), variable_declaration_stack: foliage::VariableDeclarationStack::new(),
@ -98,6 +103,16 @@ pub fn translate(program: &str) -> i32
} }
} }
fn universal_closure(scoped_formula: ScopedFormula) -> foliage::Formula
{
match scoped_formula.free_variable_declarations.is_empty()
{
true => scoped_formula.formula,
false => foliage::Formula::for_all(scoped_formula.free_variable_declarations,
Box::new(scoped_formula.formula)),
}
}
fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crate::Error> fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crate::Error>
{ {
use super::common::FindOrCreatePredicateDeclaration; use super::common::FindOrCreatePredicateDeclaration;
@ -105,9 +120,6 @@ fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crat
let head_type = determine_head_type(rule.head(), let head_type = determine_head_type(rule.head(),
|name, arity| context.predicate_declarations.find_or_create(name, arity))?; |name, arity| context.predicate_declarations.find_or_create(name, arity))?;
let mut definitions
= std::collections::BTreeMap::<std::rc::Rc<foliage::PredicateDeclaration>, Definitions>::new();
let declare_predicate_parameters = |predicate_declaration: &foliage::PredicateDeclaration| let declare_predicate_parameters = |predicate_declaration: &foliage::PredicateDeclaration|
{ {
std::rc::Rc::new((0..predicate_declaration.arity) std::rc::Rc::new((0..predicate_declaration.arity)
@ -115,13 +127,14 @@ fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crat
.collect()) .collect())
}; };
match head_type match &head_type
{ {
HeadType::SingleAtom(head_atom) => HeadType::SingleAtom(head_atom)
| HeadType::ChoiceWithSingleAtom(head_atom) =>
{ {
if !definitions.contains_key(&head_atom.predicate_declaration) if !context.definitions.contains_key(&head_atom.predicate_declaration)
{ {
definitions.insert(std::rc::Rc::clone(&head_atom.predicate_declaration), context.definitions.insert(std::rc::Rc::clone(&head_atom.predicate_declaration),
Definitions Definitions
{ {
head_atom_parameters: declare_predicate_parameters(&head_atom.predicate_declaration), head_atom_parameters: declare_predicate_parameters(&head_atom.predicate_declaration),
@ -129,7 +142,7 @@ fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crat
}); });
} }
let definitions = definitions.get_mut(&head_atom.predicate_declaration).unwrap(); let definitions = context.definitions.get_mut(&head_atom.predicate_declaration).unwrap();
context.variable_declaration_stack.push(std::rc::Rc::clone( context.variable_declaration_stack.push(std::rc::Rc::clone(
&definitions.head_atom_parameters)); &definitions.head_atom_parameters));
@ -140,6 +153,18 @@ fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crat
assert_eq!(definitions.head_atom_parameters.len(), head_atom.arguments.len()); assert_eq!(definitions.head_atom_parameters.len(), head_atom.arguments.len());
if let HeadType::ChoiceWithSingleAtom(_) = head_type
{
let head_arguments = definitions.head_atom_parameters.iter()
.map(|x| Box::new(foliage::Term::variable(x)))
.collect::<Vec<_>>();
let head_predicate = foliage::Formula::predicate(&head_atom.predicate_declaration,
head_arguments);
definition_arguments.push(Box::new(head_predicate));
}
let mut head_atom_arguments_iterator = head_atom.arguments.iter(); let mut head_atom_arguments_iterator = head_atom.arguments.iter();
for head_atom_parameter in definitions.head_atom_parameters.iter() for head_atom_parameter in definitions.head_atom_parameters.iter()
@ -168,15 +193,36 @@ fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crat
formula: definition, formula: definition,
}; };
log::trace!("translated rule with single atom in head: {:?}", definition.formula); log::debug!("translated rule with single atom in head: {:?}", definition.formula);
definitions.definitions.push(definition); definitions.definitions.push(definition);
}, },
HeadType::ChoiceWithSingleAtom(_) =>
log::debug!("translating choice rule with single atom"),
HeadType::IntegrityConstraint => HeadType::IntegrityConstraint =>
log::debug!("translated integrity constraint"), {
HeadType::Trivial => log::debug!("skipping trivial rule"), let arguments = translate_body(rule.body(),
&mut context.function_declarations, &mut context.predicate_declarations,
&mut context.variable_declaration_stack)?;
let mut free_variable_declarations = vec![];
std::mem::swap(&mut context.variable_declaration_stack.free_variable_declarations,
&mut free_variable_declarations);
let and = foliage::Formula::and(arguments);
let not = foliage::Formula::not(Box::new(and));
let scoped_formula = ScopedFormula
{
free_variable_declarations,
formula: not,
};
let integrity_constraint = universal_closure(scoped_formula);
log::debug!("translated integrity constraint: {:?}", integrity_constraint);
context.integrity_constraints.push(Box::new(integrity_constraint));
},
HeadType::Trivial => log::info!("skipping trivial rule"),
} }
Ok(()) Ok(())