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
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
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
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
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)