Skip to content

How to use Konclude for modal logic reasoning? #25

@cormackikkert

Description

@cormackikkert

Hi,

I'm trying to run Konclude on some modal logic formula. These formula are monomodal K with converse.

I think I have a translator going, but I'm finding some formula are satisfiable, but Konclude says it is unsatisfiable. I am not sure if this is due to misunderstanding the semantics of owl ontologies, or misusing Konclude, but I was wondering if there is anything I am doing wrong?

My translator is below (with a 'small' example that is satisfiable, but Konclude says is unsatisfiable)

from lark import Lark, Transformer, v_args
modal_logic_grammar = """
start: expr
?expr: "~" expr -> not_expr
    | "(" expr ")"
    | diamond_expr
    | box_expr
    | expr "&" expr -> and_expr
    | expr "|" expr -> or_expr
    | expr "=>" expr -> implies_expr
    | expr "<=>" expr -> equiv_expr
    | TOP -> top
    | BOTTOM -> bottom
    | ID -> var_expr
diamond_expr: "<" "r" ID INVERSE? ">" expr -> diamond_expr
box_expr: "[" "r" ID INVERSE? "]" expr -> box_expr
ID: /[a-z0-9_]+/
INVERSE: "-"
TOP: "true"
BOTTOM: "false"
%import common.WS
%ignore WS
"""

class ModalLogicToOWL(Transformer):
    def __init__(self):
        self.variables = set()
        self.relations = set()

    def var_expr(self, items):
        self.variables.add(items[0])
        return f":{items[0]}"

    def not_expr(self, items):
        return f"ObjectComplementOf({items[0]})"

    def and_expr(self, items):
        return f"ObjectIntersectionOf({items[0]} {items[1]})"

    def or_expr(self, items):
        return "ObjectUnionOf({} {})".format(*items)

    def implies_expr(self, items):
        return "ObjectUnionOf(ObjectComplementOf({}) {})".format(*items)

    def equiv_expr(self, items):
        return "EquivalentClasses({} {})".format(*items)

    def diamond_expr(self, items):
        relation = f":R{items[0]}"
        self.relations.add(relation)
        if len(items) > 2 and items[1] == "-":
            relation = f"ObjectInverseOf({relation})"
        return f"ObjectSomeValuesFrom({relation} {items[-1]})"

    def box_expr(self, items):
        relation = f":R{items[0]}"
        self.relations.add(relation)
        if len(items) > 2 and items[1] == "-":
            relation = f"ObjectInverseOf({relation})"
        return f"ObjectAllValuesFrom({relation} {items[-1]})"

    def top(self, items):
        return "owl:Thing"

    def bottom(self, items):
        return "owl:Nothing"

    def multi_and_expr(self, items):
        if len(items) == 1:
            return f"{items[0]}"
        if len(items) == 2:
            return self.and_expr(items)
        else:
            return f"ObjectIntersectionOf({items[0]} {self.multi_and_expr(items[1:])})"


    def start(self, items):
        declarations = "\n".join([
            f"Declaration(Class(:D0))"] +
            [f"Declaration(Class(:{var}))" for var in self.variables] +
            [f"Declaration(ObjectProperty({rel}))" for rel in self.relations])

        owl = f"""
Prefix(:=<http://www.example.com/ontology#>)
Ontology(<http://www.example.com/ontology>
    {declarations}
    EquivalentClasses(:D0
        {self.multi_and_expr(items)}
    )
)
        """
        return owl

modal_logic_parser = Lark(modal_logic_grammar, parser='lalr', transformer=ModalLogicToOWL())
parse = modal_logic_parser.parse

def modal_to_owl(modal_str):
    return parse("("+modal_str + ")")

# Usage
example = """
(v1 | v2 | ~v3 | ([r1]([r1]~v1))) & (v1 | v4 | ~v2 | ([r1]([r1]~v1))) & (v1 | v4 | ([r1-]([r1-]v2)) | ([r1-]([r1-]~v1))) & (v1 | ~v2 | ([r1]([r1]v3)) | ([r1-]v2)) & (v2 | v3 | ([r1]([r1]v2)) | ([r1-]([r1-]v1))) & (v2 | ~v1 | ~v4 | ([r1-]([r1-]v1))) & (v2 | ~v4 | ([r1]([r1]v4)) | ([r1-]~v3)) & (v2 | ([r1-]v2) | ([r1-]~v4) | ([r1-]([r1-]v1))) & (v3 | v4 | ~v2 | ([r1-]([r1-]~v3))) & (v3 | ~v2 | ([r1]([r1]v2)) | ([r1-]([r1-]~v1))) & (v3 | ~v2 | ([r1]([r1]~v3)) | ([r1-]v3)) & (v3 | ([r1-]~v3) | ([r1-]([r1-]v1)) | ([r1-]([r1-]v2))) & (v4 | ~v1 | ([r1]([r1]~v2)) | ([r1-]([r1-]v4))) & (v4 | ([r1]~v2) | ([r1]([r1]v2)) | ([r1-]([r1-]v4))) & (~v2 | ([r1]([r1]~v1)) | ([r1]([r1]~v3)) | ([r1]([r1]~v4))) & (~v2 | ([r1]([r1]~v1)) | ([r1-]v1) | ([r1-]v2)) & (~v3 | ([r1]~v2) | ([r1]([r1]~v1)) | ([r1-]~v4)) & (~v4 | ([r1]v2) | ([r1]v4) | ([r1-]([r1-]~v2))) & (~v4 | ([r1]~v3) | ([r1-]~v2) | ([r1-]([r1-]~v3))) & (~v4 | ([r1]([r1]v3)) | ([r1-]([r1-]v3)) | ([r1-]([r1-]~v4))) & (<r1>true) & (<r1->true)
"""
if __name__ == "__main__":
    owl_str = modal_to_owl(example)
    print(owl_str)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions