Source code for post_process

    Copyright 2019 Simon Vandevelde, Bram Aerts, Joost Vennekens
    This code is licensed under GNU GPLv3 license (see LICENSE) for more
    This file is part of the cDMN solver.
import re
from typing import Dict
from collections import defaultdict

[docs] def merge_definitions(idp: str) -> str: """ In cDMN, it is possible to create different tables that each define the same concept. In cases where relations are defined, this can be problematic. E.g., in the `Vacation_Days_Advanced_old` example, we define the `Employee eligible for Rule` relation in 5 different tables, each for a different value of `Rule`. In IDP, a definition is expected to be complete: all possible values for the defined concept should be defined. All other values are implicitly impossible. Because the cDMN implementation creates 5 different definitions, each defining a different value, this results in an unsat in IDP. The solution to this problem is to merge all tables defining the same concept. """ # Grab all rules and their annotations. rules = re.findall(r"(\t\t\[.*?\])?\n(.+?)(?=<-)(.+?)(?=\.\n)", idp) # Remove all rules. new_idp = re.sub(r"(\[.*?\])?\n(.+?)(?=<-)(.+?)(?=\.\n)", "", idp) defined_concepts: Dict[str, str] = {} defined_concepts = defaultdict(list) # Go over every rule and identify the defined variable. for annotation, head, body in rules: rule = annotation + '\n' + head + body + '.' defined_concept = head.split(":")[-1].split("(")[0].strip() defined_concepts[defined_concept].append(rule) # Grab the common definition annotations, try to find out what concept they # annotate. If multiple annotations exist for the same concept, we need to # merge them as well. definition_annotations = re.findall(r"\[\#(.*?)\#\]\n\t{(.*?)<-", idp, re.DOTALL) # def_annotations: Dict[str, str] = [] def_annotations = defaultdict(list) for annotation, rule in definition_annotations: defined_concept = head.split('\t')[-1].split(":")[-1].split("(")[0].strip() def_annotations[defined_concept].append(annotation) # Remove all { .. } new_idp = re.sub(r"\t{[\t\n\.]*?}", "", new_idp) new_idp = re.sub(r"\t\[(.*?)\]\n\n", "", new_idp) for key, val in defined_concepts.items(): new_idp += f"\t[{' OR '.join(def_annotations[key])}]\n" new_idp += "\t{\n" new_idp += ''.join(val) new_idp += "\n\t}\n" return new_idp