def contraction(belief_base, query):
    remainder = set()
    belief_base_copy = copy.deepcopy(belief_base)

    for clause in belief_base_copy.pop().args:
        if ~(pl_resolution({clause}, query)):
            remainder.add(clause)

    if remainder.__len__() < 3:
        if ~pl_resolution(remainder, query):
            return convert_to_logicand(remainder)

        return select_function(remainder, query)

    remainder_combinations = generate_remainders(remainder, query)

    return select_function(remainder_combinations, query)
def postulate_succeed(outcome, query):
    if pl_resolution(set(utils.dissociate(And, outcome)), query):
        print(
            "Succeed postulate failed. Query was found to be a logical consequence"
        )
        return False
    else:
        print("Succeed postulate satisfied")
        return True
def generate_remainders_rec(query_set, query):
    temp_set_gen_rec = set()
    if pl_resolution(query_set, query) & (query_set.__len__() > 2):
        for clause in query_set:
            gen_rem_set_rec = generate_remainders_rec(
                query_set.difference({clause}), query)
            temp_set_gen_rec.update(gen_rem_set_rec)
    else:
        if query_set.__len__() > 2:
            temp_set_gen_rec.add(frozenset(query_set))
    return temp_set_gen_rec
def postulate_uniformity(outcome, original, p_and_q):
    import belief_revision
    if isinstance(p_and_q, And):
        conjunctions = utils.conjuncts(p_and_q)  # split into p and q

    else:
        print("Uniformity postulate is only relevant on conjunctions")
        return True

    for sub_A in original:
        if pl_resolution(sub_A, q):
            if not pl_resolution(sub_A, p):
                return False  # Did not hold for every subset that satisfied q ∈ Cn(A')
    result = belief_revision.contraction(original,
                                         p) == belief_revision.contraction(
                                             original, q)
    if result:
        return True
    else:
        False  # Then A % p = A % q
def revision(belief_base, query):
    if ~(pl_resolution(belief_base, ~query)):
        return {belief_base.pop() & query}

    outcome = {contraction(belief_base, ~query) & query}
    BeliefBase.postulate_succeed(
        outcome,
        ~query)  # Test succeed postulate (Outcome does not contain query)
    BeliefBase.postulate_inclusion(
        outcome, belief_base)  # Test Inclusion postulate (A%p is subset of A)
    BeliefBase.postulate_vacuity(
        belief_base, outcome, ~query
    )  # Test Vacuity postulate, if query did not exist in beginning nothing happens
    # BeliefBase.postulate_relevance(belief_base, outcome, ~query)
    # BeliefBase.postulate_uniformity(outcome, belief_base, ~query, query)  # Test Uniformity -
    return outcome
def generate_remainders(clause_set, query):
    temp_set = set()

    for clause_element in clause_set:
        new_element = copy.deepcopy(clause_set)
        new_element.remove(clause_element)
        temp_set.add(frozenset(new_element))

    temp_set_gen = set()
    for query_set_element in temp_set:
        unfrozen_set = set()
        for item in query_set_element:
            unfrozen_set.add(item)
        if pl_resolution(unfrozen_set, query):
            for clause in unfrozen_set:
                gen_rem_set = generate_remainders_rec(
                    unfrozen_set.difference({clause}), query)
                temp_set_gen.update(gen_rem_set)
        else:
            temp_set_gen.add(query_set_element)

    return temp_set_gen