예제 #1
0
def apply_substitution_to_term(term: Term, substitution: Dict[str,
                                                              Term]) -> Term:
    complete_substitution = {}

    # NOTE: all variables in the term need to be defined in the substitution
    for var in term.variables():
        complete_substitution[var.name] = Var(var.name)

    complete_substitution.update(substitution)

    term_substitution = term.apply(complete_substitution)
    return term_substitution
예제 #2
0
def unify_value_different_contexts(value1: Term, value2: Term, source_values, target_values):
    """
    Unify two values that exist in different contexts.
    Updates the mapping of variables from value1 to values from value2.

    :param value1:
    :param value2:
    :param source_values: mapping of source variable to target value
    :param target_values: mapping of target variable to TARGET value
    """
    # Variables are negative numbers or None
    if is_variable(value1) and is_variable(value2):
        if value1 is None:  # value1 is anonyous var
            pass
        elif value2 is None:  # value2 is anonymous
            pass
        else:
            # Two named variables

            # Check whether value2 is already linked to another value in the target context
            sv2 = target_values.get(value2, value2)
            if sv2 == value2:  # no
                # Check whether value1 is already linked to a value
                sv1 = source_values.get(value1)
                if sv1 is None:  # no
                    # We can link variable 1 with variable 2
                    source_values[value1] = value2
                else:
                    # yes: we need to unify sv1 and value2 (they both are in target scope)
                    unify_value(sv1, value2, target_values)
            else:
                # value2 is already linked to another value
                # we need to unify value1 with that value
                unify_value_different_contexts(value1, sv2, source_values, target_values)
    # only value1 is a variable; value2 is a nonvar term
    elif is_variable(value1):
        if value1 is None:
            pass
        else:
            sv1 = source_values.get(value1)
            if sv1 is None:
                source_values[value1] = value2
            elif is_variable(sv1):
                if sv1 in value2.variables():
                    raise OccursCheck()
                if sv1 != value2:
                    target_values[sv1] = value2
                source_values[value1] = value2
            else:
                # unify in same context target_values
                source_values[value1] = unify_value(source_values[value1], value2, target_values)
    # only value2 is a variable; value1 is a nonvar term
    elif is_variable(value2):
        sv2 = target_values.get(value2)
        if sv2 is None:
            target_values[value2] = value1.apply(source_values)
        elif is_variable(sv2):
            pass
        else:
            unify_value_different_contexts(value1, sv2, source_values, target_values)

    # value1 and value2 are both not variables
    # but they are terms with the same signature
    elif value1.signature == value2.signature:  # Assume Term
        for a1, a2 in zip(value1.args, value2.args):
            unify_value_different_contexts(a1, a2, source_values, target_values)
    # they don't have the same signature
    else:
        raise UnifyError()