Source code for pyModelChecking.PL.language
"""
.. module:: language
:synopsis: Represents formulas and propositional logics.
.. moduleauthor:: Alberto Casagrande <acasagrande@units.it>
"""
import sys
from .. import language as BooleanLogics
from ..language import get_alphabet
[docs]class Formula(BooleanLogics.Formula):
r''' A class to represent propositional formulas.
Formulas are represented as nodes in labelled trees: leaves are terminal
symbols (e.g., atomic propositions and Boolean values), while internal
nodes correspond to operators and quantifiers. The ariety of internal nodes
depends on the kind of operator or quantifier must be represented.
For instance, the arity of a node representing the formula
:math:`not (p \lor True)` is one because the formula has exclusively one
sub-formula, i.e., :math:`p \lor True`. On the contrary, this last formula
has two sub-formulas, i.e., :math:`p` and :math:`True`, thus, the node
representing it has two sons.
'''
__desc__ = 'propositional formula'
def __init__(self, *phi):
self.wrap_subformulas(phi, sys.modules[self.__module__].Formula)
[docs] def wrap_subformulas(self, subformulas, FormulaClass):
r''' Replaces subformulas of the current object
This method replaces the subformulas of the current object by
using the :class:`FormulaClass` objects representing the
elements of :param subformulas:.
:param self: this object
:type self: PL.Formula
:param subformulas: the set of objects to be used as model for the
replacement
:type subformulas: Container
:param FormulaClass: the final class of the new subformulas
:type FormulaClass: class
'''
def err_msg(phi):
return ('expected a {}, '.format(FormulaClass.__desc__) +
'got the {} {}'.format(phi.__desc__, phi))
Lang = sys.modules[self.__module__]
self._subformula = []
self.height = 0
for phi in subformulas:
if isinstance(phi, bool):
self._subformula.append(Lang.Bool(phi))
else:
if isinstance(phi, str):
self._subformula.append(Lang.AtomicProposition(phi))
else:
if not isinstance(phi, FormulaClass):
if (isinstance(phi, Lang.Formula) or
not isinstance(phi, Formula)):
raise TypeError(err_msg(phi))
phi = phi.cast_to(Lang)
if not isinstance(phi, FormulaClass):
raise TypeError(err_msg(phi))
self._subformula.append(phi)
self.height = max(self.height, phi.height+1)
[docs] def cast_to(self, Lang):
r''' Casts the current object in a formula of a different class.
:param self: this formula
:type self: Formula
:param Lang: a class representing a language
:type self: class
:returns: a syntactically equivalent formula in language represented by
:class:`Lang`
:rtype: Lang
'''
if isinstance(self, Bool):
return Lang.Bool(bool(self._value))
if isinstance(self, AtomicProposition):
return Lang.AtomicProposition(str(self.name))
symbol_name = self.__class__.__name__
if symbol_name not in Lang.alphabet:
raise TypeError('{} is not in the alphabet '.format(symbol_name) +
'of {}, thus {} is '.format(Lang.__name__, self) +
'not a {} formula'.format(Lang.__name__))
subformulas = []
for subformula in self.subformulas():
subformulas.append(Formula.cast_to(subformula, Lang))
return Lang.alphabet[symbol_name](*subformulas)
[docs]class AtomicProposition(Formula, BooleanLogics.AlphabeticSymbol):
r'''
The class representing atomic propositionic propositions.
'''
def __init__(self, name):
r''' Initialize a atomic proposition.
This method builds a atomic propositionic proposition.
:param name: the name of the atomic proposition.
:type name: str
'''
if not isinstance(name, str):
raise TypeError('name = \'{}\' must be '.format(name) +
'a {} object, but it is '.format(str) +
'{} object'.format(name.__class__))
self.name = str(name)
self.height = 0
[docs] def clone(self):
r''' Clones an atomic proposition
:returns: a clone of the current atomic proposition
:rtype: PL.AtomicProposition
'''
return self.__class__(str(self.name))
[docs] def subformula(self, i):
r''' Returns the :math:`i`-th subformula.
:param i: the index of the subformula to be returned
:type i: Integer
:raise TypeError: atomic propositions have not subformulas
'''
raise TypeError('AtomicPropositions have not subformulas.')
[docs] def subformulas(self):
r''' Returns the list of all the subformulas.
:returns: returns the empty list of the subformulas of the current
formula
:rtype: list
'''
return []
def __str__(self):
return '{}'.format(self.name)
[docs]class Bool(BooleanLogics.Bool, AtomicProposition):
r'''
The class of Boolean atomic propositions.
'''
pass
[docs]class LogicOperator(Formula, BooleanLogics.LogicOperator):
r'''
A class to represent logic operator such as :math:`\land` or :math:`\lor`.
'''
pass
[docs]class Or(LogicOperator, BooleanLogics.Or):
r'''
Represents logic non-exclusive disjunction.
'''
pass
[docs]def get_symbols(alphabet):
symbols = list()
for name, c in alphabet.items():
if name == 'Bool':
symbols.extend(Bool.symbols.values())
else:
if name != 'AtomicProposition':
symbols.extend(c.symbols)
return symbols
alphabet = get_alphabet(__name__)
symbols = get_symbols(alphabet)