Beispiel #1
0
def use_rule(name: str, branch: list[utils.Sentence], used: utils.History, context: dict[str, tp.Any], decisions: dict[str, tp.Any]) -> tuple[utils.SentenceTupleStructure, utils.HistoryTupleStructure, dict[str, tp.Any]]:
    """
    Używa określonej reguły na podanej gałęzi.
    Więcej: https://www.notion.so/szymanski/Gniazda-w-Larchu-637a500c36304ee28d3abe11297bfdb2#98e96d34d3c54077834bc0384020ff38

    :param name: Nazwa używanej reguły, listę można uzyskać z pomocą Formal.get_rules_docs()
    :type name: str
    :param branch: Lista zdań w gałęzi, na której została użyta reguła
    :type branch: list[utils.Sentence]
    :param used: Obiekt historii przechowujący informacje o już rozłożonych zdaniach
    :type used: utils.History
    :param context: kontekst wymagany do zastosowania reguły, listę można uzyskać z pomocą Formal.get_needed_context(rule)
        Kontekst reguł: https://www.notion.so/szymanski/Zarz-dzanie-kontekstem-regu-2a5abea2a1bc492e8fa3f8b1c046ad3a
    :type context: dict[str, tp.Any]
    :param decisions: Decyzje podjęte samodzielnie przez algorytm, pozwalają na odtworzenie dowoduz zapisanego pliku.
    :type context: dict[str, tp.Any]
    :return: Struktura krotek, reprezentująca wynik reguły oraz strukturę reprezentującą operacje do wykonania na zbiorze zamknięcia.
        Struktury krotek: https://www.notion.so/szymanski/Reprezentacja-dowod-w-w-Larchu-cd36457b437e456a87b4e0c2c2e38bd5#014dccf44246407380c4e30b2ea598a9
        Zamykanie gałęzi: https://www.notion.so/szymanski/Zamykanie-ga-zi-53249279f1884ab4b6f58bbd6346ec8d
    :rtype: tuple[tp.Union[tuple[tuple[utils.Sentence]], None], tp.Union[tuple[tuple[tp.Union[int, Callable, utils.Sentence]]], None]]
    """
    rule = RULES[name]

    start = utils.strip_around(branch[-1], "turnstile", False, PRECEDENCE)
    start_left, start_right = start[0]

    # Check sequent number
    if context.get('partID', -1) > sum(i.startswith('sep') for i in start_left)+1:
        raise utils.FormalError("Sequent number is too big")

    # Loop detection
    history = None
    if name == "left imp":
        if tuple(start_right) in used:
            raise utils.FormalError("Operation prohibited by loop detection algorithm")
        else:
            history = [[start_right], [0]]
    elif name == 'left or':
        history = [[-1], [-1]]
    elif name == 'right imp':
        l = utils.strip_around(start_right, "imp", False, PRECEDENCE)
        if l is None:
            return None, None, None
        elif is_sequent(start_left, l[0][0]):
            history = [[0]]
        else:
            history = [[-1]]

    # Rule usage
    left, right = rule.func(start_left[:], start_right[:], *context.values())

    # Outcome return
    if left is not None and right is not None:
        # History length multiplication
        if not history:
            history = [[0]]*len(left)
        return utils.merge_tupstruct(left, right, "turnstile_=>"), history, None
    else:
        return None, None, None
Beispiel #2
0
def check_closure(
        branch: list[utils.Sentence], used: set[tuple[str]]
) -> tp.Union[None, tuple[utils.close.Close, str]]:
    """Sprawdza możliwość zamknięcia gałęzi, zwraca obiekty zamknięcia oraz komunikat do wyświetlenia"""
    left, right = utils.strip_around(branch[-1], "turnstile", False,
                                     PRECEDENCE)[0]
    left = [i for i in left if i != "^"]
    seps = sum((i.startswith('sep_') for i in left), 1)

    # Right part verification
    empty = len(right) == 1

    # Left part verification
    if not left:
        return None
    for i in range(seps):
        f = utils.pop_part(left[:], 'sep', i)

        # F, ... => ...
        if len(f) == 1 and f[0].startswith("falsum_"):
            return utils.close.Falsum, "Falsum found on the left"

        # p, ... => p
        if f == right:
            return utils.close.Axiom, "Sequent on the right corresponds with a sequent on the left"

        # Detect finish
        empty &= not any((any((j.startswith(i) for j in f))
                          for i in ('and_', 'or_', 'imp_')))

    if empty:
        return utils.close.Emptiness, "Nothing more can be done with this branch, so it was closed."
Beispiel #3
0
def rule_right_or(left: utils.Sentence, right: utils.Sentence, side: str,
                  used: list[tuple[str]]):
    # sourcery skip: merge-duplicate-blocks
    """ ... => (A,B)[side]
        ______________
        ... => AvB
    """
    # Usunięto find bo trochę przesadne chwilowo
    if not right or side not in ('l', 'r'):
        return (None, None)

    split = utils.strip_around(right, 'or', False, PRECEDENCE)
    if split is None or split[0] is None:
        return (None, None)
    left_split, right_split = split[0]

    if side == 'l':
        return ((left, ), ), ((left_split, ), )
    elif side == 'r':
        return ((left, ), ), ((right_split, ), )
    else:
        if is_sequent(left, left_split):
            return ((left, ), ), ((left_split, ), )
        elif is_sequent(left, right_split):
            return ((left, ), ), ((right_split, ), )
        else:
            # Default case
            return ((left, ), ), ((max(split[0], key=len), ), )

    if ret in used:
        raise utils.FormalError(
            "Operation prohibited by loop detection algorithm")
    utils.pop_part(right, 'sep', 0)
    return ((left, ), ), ((debrac(ret), ), )
Beispiel #4
0
def rule_right_or(left: utils.Sentence, right: utils.Sentence, side: str):
    # sourcery skip: merge-duplicate-blocks
    
    """ ... => (A,B)[side]
        ______________
        ... => AvB
    """
    # Usunięto find bo trochę przesadne chwilowo
    if not right or side not in ('l', 'r'):
        return (None, None)
    
    split = utils.strip_around(right, 'or', False, PRECEDENCE)
    if split is None or split[0] is None:
        return (None, None)
    left_split, right_split = split[0]
    
    if side=='l':
        return ((left,),), ((left_split,),)
    elif side=='r':
        return ((left,),), ((right_split,),)
    else:
        if is_sequent(left, left_split):
            return ((left,),), ((left_split,),)
        elif is_sequent(left, right_split):
            return ((left,),), ((right_split,),)
        else:
            # Default case
            return ((left,),), ((max(split[0], key=len),),)
Beispiel #5
0
def rule_right_and(left: utils.Sentence, right: utils.Sentence):
    """ ... => A      ... => B
        __________________________
        ... => A&B
    """
    conj = utils.pop_part(right, 'sep', 0)
    if conj is None:
        return (None, None)

    split = utils.strip_around(conj, 'and', False, PRECEDENCE)
    if split is None or split[0] is None:
        return (None, None)
    split = split[0]
    return ((left,),(left,),), ((split[0],),(split[1],),)
Beispiel #6
0
def rule_left_or(left: utils.Sentence, right: utils.Sentence, num: int):
    """ A,... => ...  B,... => ...
        __________________________
        AvB,... => ...
    """
    try:
        conj = utils.pop_part(left, 'sep', num-1)
    except IndexError:
        return (None, None)
    
    split = utils.strip_around(conj, 'or', False, PRECEDENCE)
    if split is None or split[0] is None:
        return (None, None)
    split = split[0]
    return ((split[0]+sep(left)+left,),(split[1]+sep(left)+left,),), ((right,),(right,),)
Beispiel #7
0
def rule_right_imp(left: utils.Sentence, right: utils.Sentence):
    """ ..., A => B
        ______________
        ... => A -> B
    """
    try:
        conj = utils.pop_part(right, 'sep', 0)
    except IndexError:
        return (None, None)
    
    split = utils.strip_around(conj, 'imp', False, PRECEDENCE)
    if split is None or split[0] is None:
        return (None, None)
    split = split[0]
    return ((split[0]+sep(left)+left,),), ((split[1],),)
Beispiel #8
0
def rule_left_imp(left: utils.Sentence, right: utils.Sentence, num: int):
    """ A -> B, ... => A    B,... => ...
        ________________________________
        A -> B,... => ...
    """
    try:
        conj = utils.pop_part(left, 'sep', num - 1)
    except IndexError:
        return (None, None)

    split = utils.strip_around(conj, 'imp', False, PRECEDENCE)
    if split is None or split[0] is None:
        return (None, None)
    split = split[0]
    return (
        (conj + sep(left) + left, ),
        (debrac(split[1]) + sep(left) + left, ),
    ), (
        (debrac(split[0]), ),
        (right, ),
    )
Beispiel #9
0

PRECEDENCE = {'and': 3, 'or': 3, 'imp': 2, 'not': 4}


def red_neg(x):
    return utils.reduce_prefix(x, 'not', PRECEDENCE)


RULES = {
    'true and':
    utils.Rule(
        symbolic="A and B / A; B",
        docs=
        "Rozkładanie prawdziwej koniunkcji. Wymaga wskazania zdania w gałęzi.",
        func=lambda x: utils.strip_around(x, 'and', False, PRECEDENCE),
        context=None,
        reusable=False),
    'false and':
    utils.Rule(
        symbolic="~(A and B) / ~A | ~B",
        docs=
        "Rozkładanie fałszywej koniunkcji. Wymaga wskazania zdania w gałęzi.",
        func=lambda x: utils.add_prefix(
            utils.strip_around(red_neg(x), 'and', True, PRECEDENCE), 'not', '~'
        ),
        context=None,
        reusable=False),
    'false or':
    utils.Rule(
        symbolic="~(A or B) / ~A; ~B",
Beispiel #10
0
def use_rule(
    name: str, branch: list[utils.Sentence], used: utils.History,
    context: dict[str, tp.Any], decisions: dict[str, tp.Any]
) -> tuple[utils.SentenceTupleStructure, utils.HistoryTupleStructure, dict[
        str, tp.Any]]:
    """
    Używa określonej reguły na podanej gałęzi.
    Więcej: https://www.notion.so/szymanski/Gniazda-w-Larchu-637a500c36304ee28d3abe11297bfdb2#98e96d34d3c54077834bc0384020ff38

    :param name: Nazwa używanej reguły, listę można uzyskać z pomocą Formal.get_rules_docs()
    :type name: str
    :param branch: Lista zdań w gałęzi, na której została użyta reguła
    :type branch: list[utils.Sentence]
    :param used: Obiekt historii przechowujący informacje o już rozłożonych zdaniach
    :type used: utils.History
    :param context: kontekst wymagany do zastosowania reguły, listę można uzyskać z pomocą Formal.get_needed_context(rule)
        Kontekst reguł: https://www.notion.so/szymanski/Zarz-dzanie-kontekstem-regu-2a5abea2a1bc492e8fa3f8b1c046ad3a
    :type context: dict[str, tp.Any]
    :param auto: , defaults to False
    :type auto: bool, optional
    :return: Struktura krotek, reprezentująca wynik reguły oraz strukturę reprezentującą operacje do wykonania na zbiorze zamknięcia.
        Struktury krotek: https://www.notion.so/szymanski/Reprezentacja-dowod-w-w-Larchu-cd36457b437e456a87b4e0c2c2e38bd5#014dccf44246407380c4e30b2ea598a9
        Zamykanie gałęzi: https://www.notion.so/szymanski/Zamykanie-ga-zi-53249279f1884ab4b6f58bbd6346ec8d
    :rtype: tuple[tp.Union[tuple[tuple[utils.Sentence]], None], tp.Union[tuple[tuple[tp.Union[int, Callable, utils.Sentence]]], None]]
    """
    rule = RULES[name]

    start = utils.strip_around(branch[-1], "turnstile", False, PRECEDENCE)
    start_left, start_right = start[0]

    # Check sequent number
    if context.get('partID',
                   -1) > sum(i.startswith('sep') for i in start_left) + 1:
        raise utils.FormalError("Sequent number is too big")

    # Loop detection
    history = None
    if name == "left imp":
        p = utils.pop_part(start_left[:], 'sep', context['partID'] - 1)
        l, r = utils.strip_around(p, "imp", False, PRECEDENCE)[0]
        if tuple(l) in used:
            raise utils.FormalError(
                "Operation prohibited by loop detection algorithm")
        else:
            history = [[l], [0]]

    elif name == 'left or':
        p = utils.pop_part(start_left[:], 'sep', context['partID'] - 1)
        l, r = utils.strip_around(p, "or", False, PRECEDENCE)[0]
        if is_sequent(start_left, l) or is_sequent(start_left, r):
            raise utils.FormalError(
                "Operation prohibited by loop detection algorithm")
        else:
            history = [[-1, start_right], [-1, start_right]]

    elif name == 'right imp':
        if (stripped := utils.strip_around(start_right, "imp", False,
                                           PRECEDENCE)) is None:
            return None, None, None
        l, r = stripped[0]
        if is_sequent(start_left, l):
            if tuple(r) not in used:
                history = [[r]]
            else:
                raise utils.FormalError(
                    "Operation prohibited by loop detection algorithm")
        else:
            history = [[-1, r]]
Beispiel #11
0
    elif name == 'right imp':
        if (stripped := utils.strip_around(start_right, "imp", False,
                                           PRECEDENCE)) is None:
            return None, None, None
        l, r = stripped[0]
        if is_sequent(start_left, l):
            if tuple(r) not in used:
                history = [[r]]
            else:
                raise utils.FormalError(
                    "Operation prohibited by loop detection algorithm")
        else:
            history = [[-1, r]]

    elif name == 'right and':
        l, r = utils.strip_around(start_right, "and", False, PRECEDENCE)[0]
        if tuple(l) in used or tuple(r) in used:
            raise utils.FormalError(
                "Operation prohibited by loop detection algorithm")
        else:
            history = [[l], [r]]

    elif name == 'right or':
        context['used'] = used

    # Rule usage
    usage = rule.func(start_left[:], start_right[:], *context.values())
    if not usage:
        return None, None, None
    left, right = usage