Example #1
0
 def consts(self):
     if self._consts is None:
         if self.is_fun() and not self._args:
             self._consts = sortedset([self])
         else:
             self._consts = sortedset(union(a.consts for a in self._args))
     return self._consts
Example #2
0
 def terms(self):
     if self._terms is None:
         self._terms = union(a.terms for a in self._args)
         if self.is_term():
             self._terms.add(self)
         self._terms = sortedset(self._terms)
     return self._terms
Example #3
0
def optimize_given(seq, context, bound):
    assert_normal(seq)
    antecedents = sortedset(seq.antecedents - context)
    (succedent,) = list(seq.succedents)
    POMAGMA_DEBUG('{} | {} |- {}', list(bound), list(antecedents), succedent)
    plan = optimize_plan(antecedents, succedent, bound)
    plan.validate(bound)
    return plan.cost, seq, plan
Example #4
0
 def vars(self):
     if self._vars is None:
         if self._arity == 'Variable':
             self._vars = set([self])
         elif self._arity == 'NullaryFunction':
             self._vars = set()
         elif self._arity in signature.FUNCTION_ARITIES:
             self._vars = union(a.vars for a in self._args)
         else:
             self._vars = union(a.vars for a in self._args)
         self._vars = sortedset(self._vars)
     return self._vars
Example #5
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)