123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- # Natural Language Toolkit: Semantic Interpretation
- #
- # Author: Ewan Klein <ewan@inf.ed.ac.uk>
- #
- # Copyright (C) 2001-2019 NLTK Project
- # URL: <http://nltk.org/>
- # For license information, see LICENSE.TXT
- from nltk.sem.logic import (
- AllExpression,
- AndExpression,
- ApplicationExpression,
- EqualityExpression,
- ExistsExpression,
- IffExpression,
- ImpExpression,
- NegatedExpression,
- OrExpression,
- VariableExpression,
- skolem_function,
- unique_variable,
- )
- def skolemize(expression, univ_scope=None, used_variables=None):
- """
- Skolemize the expression and convert to conjunctive normal form (CNF)
- """
- if univ_scope is None:
- univ_scope = set()
- if used_variables is None:
- used_variables = set()
- if isinstance(expression, AllExpression):
- term = skolemize(
- expression.term,
- univ_scope | set([expression.variable]),
- used_variables | set([expression.variable]),
- )
- return term.replace(
- expression.variable,
- VariableExpression(unique_variable(ignore=used_variables)),
- )
- elif isinstance(expression, AndExpression):
- return skolemize(expression.first, univ_scope, used_variables) & skolemize(
- expression.second, univ_scope, used_variables
- )
- elif isinstance(expression, OrExpression):
- return to_cnf(
- skolemize(expression.first, univ_scope, used_variables),
- skolemize(expression.second, univ_scope, used_variables),
- )
- elif isinstance(expression, ImpExpression):
- return to_cnf(
- skolemize(-expression.first, univ_scope, used_variables),
- skolemize(expression.second, univ_scope, used_variables),
- )
- elif isinstance(expression, IffExpression):
- return to_cnf(
- skolemize(-expression.first, univ_scope, used_variables),
- skolemize(expression.second, univ_scope, used_variables),
- ) & to_cnf(
- skolemize(expression.first, univ_scope, used_variables),
- skolemize(-expression.second, univ_scope, used_variables),
- )
- elif isinstance(expression, EqualityExpression):
- return expression
- elif isinstance(expression, NegatedExpression):
- negated = expression.term
- if isinstance(negated, AllExpression):
- term = skolemize(
- -negated.term, univ_scope, used_variables | set([negated.variable])
- )
- if univ_scope:
- return term.replace(negated.variable, skolem_function(univ_scope))
- else:
- skolem_constant = VariableExpression(
- unique_variable(ignore=used_variables)
- )
- return term.replace(negated.variable, skolem_constant)
- elif isinstance(negated, AndExpression):
- return to_cnf(
- skolemize(-negated.first, univ_scope, used_variables),
- skolemize(-negated.second, univ_scope, used_variables),
- )
- elif isinstance(negated, OrExpression):
- return skolemize(-negated.first, univ_scope, used_variables) & skolemize(
- -negated.second, univ_scope, used_variables
- )
- elif isinstance(negated, ImpExpression):
- return skolemize(negated.first, univ_scope, used_variables) & skolemize(
- -negated.second, univ_scope, used_variables
- )
- elif isinstance(negated, IffExpression):
- return to_cnf(
- skolemize(-negated.first, univ_scope, used_variables),
- skolemize(-negated.second, univ_scope, used_variables),
- ) & to_cnf(
- skolemize(negated.first, univ_scope, used_variables),
- skolemize(negated.second, univ_scope, used_variables),
- )
- elif isinstance(negated, EqualityExpression):
- return expression
- elif isinstance(negated, NegatedExpression):
- return skolemize(negated.term, univ_scope, used_variables)
- elif isinstance(negated, ExistsExpression):
- term = skolemize(
- -negated.term,
- univ_scope | set([negated.variable]),
- used_variables | set([negated.variable]),
- )
- return term.replace(
- negated.variable,
- VariableExpression(unique_variable(ignore=used_variables)),
- )
- elif isinstance(negated, ApplicationExpression):
- return expression
- else:
- raise Exception('\'%s\' cannot be skolemized' % expression)
- elif isinstance(expression, ExistsExpression):
- term = skolemize(
- expression.term, univ_scope, used_variables | set([expression.variable])
- )
- if univ_scope:
- return term.replace(expression.variable, skolem_function(univ_scope))
- else:
- skolem_constant = VariableExpression(unique_variable(ignore=used_variables))
- return term.replace(expression.variable, skolem_constant)
- elif isinstance(expression, ApplicationExpression):
- return expression
- else:
- raise Exception('\'%s\' cannot be skolemized' % expression)
- def to_cnf(first, second):
- """
- Convert this split disjunction to conjunctive normal form (CNF)
- """
- if isinstance(first, AndExpression):
- r_first = to_cnf(first.first, second)
- r_second = to_cnf(first.second, second)
- return r_first & r_second
- elif isinstance(second, AndExpression):
- r_first = to_cnf(first, second.first)
- r_second = to_cnf(first, second.second)
- return r_first & r_second
- else:
- return first | second
|