Exemple #1
0
def get_inverses(sequent):
    '''
    Given a sequent A |- B, return set of sequents ~A |- ~B,
    dealing with multiple antecedents and succedents. For example

        A, B |- C, D

    yields the set

        A, ~B |- ~C, ~D
        ~A, B |- ~C, ~D
    '''
    result = set()
    neg_succedents = union(try_get_negated(s) for s in sequent.succedents)
    pos_antecedents = set(sequent.antecedents)
    for pos_antecedent in pos_antecedents:
        try:
            negated = try_get_negated(pos_antecedent)
        except NotNegatable:
            negated = set()
        for neg_antecedent in negated:
            neg_antecedents = set_without(pos_antecedents, pos_antecedent)
            neg_antecedents = set_with(neg_antecedents, neg_antecedent)
            result.add(Sequent(neg_antecedents, neg_succedents))
    return result
Exemple #2
0
def weaken_facts(facts, fact):
    assert fact in facts
    if fact.is_rel():
        without = set_without(facts, fact)
        yield without
        if fact.name == 'EQUAL':
            lhs, rhs = fact.args
            yield set_with(without, LESS(lhs, rhs))
            yield set_with(without, LESS(rhs, lhs))
Exemple #3
0
def get_contrapositives(seq):
    if len(seq.succedents) == 1:
        seq_succedent = iter(seq.succedents).next()
        result = set()
        for antecedent in seq.antecedents:
            if antecedent.name != 'OPTIONALLY':
                antecedents = set_without(seq.antecedents, antecedent)
                succedents = get_negated(antecedent)
                for disjunct in get_negated(seq_succedent):
                    if get_negated(disjunct) & antecedents:
                        pass  # contradiction
                    else:
                        result.add(Sequent(
                            set_with(antecedents, disjunct),
                            succedents))
        return result
    elif len(seq.succedents) > 1:
        TODO('allow multiple succedents')
    else:
        TODO('allow empty succedents')
Exemple #4
0
def get_pointed(seq):
    '''
    Return a set of sequents each with a single succedent.
    '''
    result = set()
    if len(seq.succedents) == 1:
        for succedent in seq.succedents:
            if succedent.name != 'OPTIONALLY':
                result.add(seq)
    elif len(seq.succedents) > 1:
        for succedent in seq.succedents:
            remaining = set_without(seq.succedents, succedent)
            negated = union(map(get_negated, remaining))
            # FIXME get_negated is a disjunction; do not union it
            neg_neg = union(map(get_negated, seq.antecedents))
            if not (negated & neg_neg):
                antecedents = seq.antecedents | negated
                result.add(Sequent(antecedents, set([succedent])))
    else:
        TODO('allow empty succedents')
    return result
Exemple #5
0
def get_pointed(seq):
    """Return a set of sequents each with a single succedent."""
    result = set()
    if len(seq.succedents) == 1:
        for succedent in seq.succedents:
            if succedent.name != 'OPTIONALLY':
                result.add(seq)
    elif len(seq.succedents) > 1:
        for succedent in seq.succedents:
            remaining = set_without(seq.succedents, succedent)
            try:
                neg_remaining = map(try_get_negated, remaining)
            except NotNegatable:
                continue
            for negated in itertools.product(*neg_remaining):
                try:
                    antecedents = try_simplify_antecedents(
                        set(negated) | seq.antecedents)
                except Inconsistent:
                    continue
                result.add(Sequent(antecedents, set([succedent])))
    else:
        raise ValueError('get_contrapositives never returns empty succedents')
    return result
Exemple #6
0
def optimize_plan(antecedents, succedent, bound):
    """Iterate through the space of plans, narrowing heuristically."""
    assert isinstance(antecedents, sortedset)
    assert isinstance(succedent.consts, sortedset)

    # ensure
    if not antecedents and succedent.vars <= bound:
        POMAGMA_DEBUG('ensure {}', succedent)
        return Ensure.make(succedent)

    # conditionals
    # HEURISTIC test eagerly in arbitrary order
    for a in antecedents:
        if a.is_rel():
            if a.vars <= bound:
                antecedents_a = sortedset(set_without(antecedents, a))
                POMAGMA_DEBUG('test relation {}', a)
                body = optimize_plan(antecedents_a, succedent, bound)
                return Test.make(a, body)
        else:
            assert a.is_fun(), a
            if a.vars <= bound and a.var in bound:
                antecedents_a = sortedset(set_without(antecedents, a))
                POMAGMA_DEBUG('test function {}', a)
                body = optimize_plan(antecedents_a, succedent, bound)
                return Test.make(a, body)

    # find & bind variable
    # HEURISTIC bind eagerly in arbitrary order
    for a in antecedents:
        if a.is_fun():
            if a.vars <= bound:
                assert a.var not in bound
                antecedents_a = sortedset(set_without(antecedents, a))
                bound_a = set_with(bound, a.var)
                POMAGMA_DEBUG('let {}', a)
                body = optimize_plan(antecedents_a, succedent, bound_a)
                return Let.make(a, body)
            else:
                # TODO find inverse if injective function
                pass

    results = []

    # iterate unknown
    if succedent.is_rel() and succedent.name != 'EQUAL':  # TODO handle EQUAL
        s_free = succedent.vars - bound
        if len(succedent.vars) == len(succedent.args) and len(s_free) == 1:
            v = iter(s_free).next()
            bound_v = set_with(bound, v)
            POMAGMA_DEBUG('iterate unknown {}', v)
            body = optimize_plan(antecedents, succedent, bound_v)
            results.append(Iter.make(v, Test.make(UNKNOWN(succedent), body)))

    # iterate forward
    forward_vars = set()
    for a in antecedents:
        a_free = a.vars - bound
        if len(a_free) == 1:
            forward_vars |= a_free
    for v in forward_vars:
        bound_v = set_with(bound, v)
        POMAGMA_DEBUG('iterate forward {}', v)
        body = optimize_plan(antecedents, succedent, bound_v)
        results.append(Iter.make(v, body))

    # iterate backward
    for a in antecedents:
        if a.is_fun() and a.args and a.var in bound and not (a.vars <= bound):
            nargs = len(a.args)
            a_free = a.vars - bound
            bound_v = bound | a_free
            antecedents_a = sortedset(set_without(antecedents, a))
            assert len(a_free) in [0, 1, 2]
            assert nargs in [0, 1, 2]
            POMAGMA_DEBUG('iterate backward {}', a)
            if nargs == 1 and len(a_free) == 1:
                # TODO injective function inverse need not be iterated
                body = optimize_plan(antecedents_a, succedent, bound_v)
                results.append(IterInvInjective.make(a, body))
            elif nargs == 2 and len(a_free) == 1 and len(a.vars) == 2:
                (fixed,) = list(a.vars - a_free)
                body = optimize_plan(antecedents_a, succedent, bound_v)
                results.append(IterInvBinaryRange.make(a, fixed, body))
            elif nargs == 2 and len(a_free) == 2:
                body = optimize_plan(antecedents_a, succedent, bound_v)
                results.append(IterInvBinary.make(a, body))

    # HEURISTIC iterate locally eagerly
    if results:
        return min(results)

    # iterate anything
    for v in union(a.vars for a in antecedents) | succedent.vars - bound:
        bound_v = set_with(bound, v)
        POMAGMA_DEBUG('iterate non-locally')
        body = optimize_plan(antecedents, succedent, bound_v)
        results.append(Iter.make(v, body))

    return min(results)
Exemple #7
0
def get_compiled(antecedents, succedent, bound):
    '''
    Iterate through the space of strategies, narrowing heuristically.
    '''
    POMAGMA_DEBUG('{} | {} |- {}', list(bound), list(antecedents), succedent)

    if not antecedents and succedent.vars <= bound:
        POMAGMA_DEBUG('ensure')
        return [Ensure(succedent)]

    results = []

    # bind succedent constants
    for c in succedent.consts:
        if c.var not in bound:
            bound_c = set_with(bound, c.var)
            POMAGMA_DEBUG('bind succedent constant')
            for s in get_compiled(antecedents, succedent, bound_c):
                results.append(Let(c, s))
            return results  # HEURISTIC bind eagerly in arbitrary order

    # bind antecedent constants
    for a in antecedents:
        if not a.args and a.var not in bound:
            assert a.is_fun(), a
            antecedents_a = set_without(antecedents, a)
            bound_a = set_with(bound, a.var)
            POMAGMA_DEBUG('bind antecedent constant')
            for s in get_compiled(antecedents_a, succedent, bound_a):
                results.append(Let(a, s))
            return results  # HEURISTIC bind eagerly in arbitrary order

    # conditionals
    for a in antecedents:
        # if a.name in ['LESS', 'NLESS']:
        if a.is_rel():
            if a.vars <= bound:
                antecedents_a = set_without(antecedents, a)
                POMAGMA_DEBUG('conditional')
                for s in get_compiled(antecedents_a, succedent, bound):
                    results.append(Test(a, s))
        else:
            assert a.is_fun(), a
            if a.vars <= bound and a.var in bound:
                antecedents_a = set_without(antecedents, a)
                POMAGMA_DEBUG('conditional')
                for s in get_compiled(antecedents_a, succedent, bound):
                    results.append(Test(a, s))
        if results:
            return results  # HEURISTIC test eagerly in arbitrary order

    # find & bind variable
    for a in antecedents:
        if a.is_fun():
            if a.vars <= bound:
                assert a.var not in bound
                antecedents_a = set_without(antecedents, a)
                bound_a = set_with(bound, a.var)
                POMAGMA_DEBUG('bind variable')
                for s in get_compiled(antecedents_a, succedent, bound_a):
                    results.append(Let(a, s))
            else:
                # TODO find inverse if injective function
                pass
        if results:
            return results  # HEURISTIC bind eagerly in arbitrary order

    # iterate forward
    for a in antecedents:
        # works for both Relation and Function antecedents
        if a.vars & bound:
            for v in a.vars - bound:
                bound_v = set_with(bound, v)
                POMAGMA_DEBUG('iterate forward')
                for s in get_compiled(antecedents, succedent, bound_v):
                    results.append(Iter(v, s))

    # iterate backward
    for a in antecedents:
        if a.is_fun() and a.var in bound:
            a_vars = a.vars
            a_free = a_vars - bound
            assert len(a_free) in [0, 1, 2]
            nargs = len(a.args)
            assert nargs in [0, 1, 2]
            if nargs and a_free:
                bound_v = bound | a_free
                antecedents_a = set(antecedents)
                antecedents_a.remove(a)
                POMAGMA_DEBUG('iterate backward')
                if nargs == 1 and len(a_free) == 1:
                    # TODO injective function inverse need not be iterated
                    for s in get_compiled(antecedents_a, succedent, bound_v):
                        results.append(IterInvInjective(a, s))
                elif nargs == 2 and len(a_free) == 1 and len(a_vars) == 2:
                    for s in get_compiled(antecedents_a, succedent, bound_v):
                        (fixed,) = list(a.vars - a_free)
                        results.append(IterInvBinaryRange(a, fixed, s))
                elif nargs == 2 and len(a_free) == 2:
                    for s in get_compiled(antecedents_a, succedent, bound_v):
                        results.append(IterInvBinary(a, s))

    if results:
        return results  # HEURISTIC iterate locally eagerly

    # iterate anything
    free = (union([a.vars for a in antecedents]) | succedent.vars - bound)
    for v in free:
        bound_v = set_with(bound, v)
        POMAGMA_DEBUG('iterate non-locally')
        for s in get_compiled(antecedents, succedent, bound_v):
            results.append(Iter(v, s))

    assert results
    return results