def visit_EMap(self, e): ee = self.visit(e.e) f = self.visit(e.transform_function) if f.body == f.arg: return ee elif isinstance(ee, EBinOp) and ee.op == "+": return self.visit(EBinOp(EMap(ee.e1, f).with_type(e.type), ee.op, EMap(ee.e2, f).with_type(e.type)).with_type(e.type)) elif isinstance(ee, ESingleton): return self.visit(ESingleton(f.apply_to(ee.e)).with_type(e.type)) elif isinstance(ee, EMap): return self.visit(EMap(ee.e, compose(f, ee.transform_function)).with_type(e.type)) return EMap(ee, f).with_type(e.type)
def visit_EMap(self, e): ee = self.visit(e.e) f = self.visit(e.f) if f.body == f.arg: return ee elif isinstance(ee, EBinOp) and ee.op == "+": return self.visit(EBinOp(EMap(ee.e1, f).with_type(e.type), ee.op, EMap(ee.e2, f).with_type(e.type)).with_type(e.type)) elif isinstance(ee, ESingleton): return self.visit(ESingleton(f.apply_to(ee.e)).with_type(e.type)) elif isinstance(ee, EMap): return self.visit(EMap(ee.e, compose(f, ee.f)).with_type(e.type)) return EMap(ee, f).with_type(e.type)
def visit_EFilter(self, e): ee = self.visit(e.e) f = self.visit(e.p) if f.body == T: return ee elif f.body == F: return EEmptyList().with_type(e.type) elif isinstance(ee, EBinOp) and ee.op == "+": return self.visit(EBinOp(EFilter(ee.e1, f).with_type(ee.e1.type), ee.op, EFilter(ee.e2, f).with_type(ee.e2.type)).with_type(e.type)) elif isinstance(ee, ESingleton): return self.visit(ECond( f.apply_to(ee.e), ee, EEmptyList().with_type(e.type)).with_type(e.type)) elif isinstance(ee, EMap): return self.visit(EMap(EFilter(ee.e, compose(f, ee.f)).with_type(ee.e.type), ee.f).with_type(e.type)) return EFilter(ee, f).with_type(e.type)
def visit_EFilter(self, e): ee = self.visit(e.e) f = self.visit(e.predicate) if f.body == ETRUE: return ee elif f.body == EFALSE: return EEmptyList().with_type(e.type) elif isinstance(ee, EBinOp) and ee.op == "+": return self.visit(EBinOp(EFilter(ee.e1, f).with_type(ee.e1.type), ee.op, EFilter(ee.e2, f).with_type(ee.e2.type)).with_type(e.type)) elif isinstance(ee, ESingleton): return self.visit(ECond( f.apply_to(ee.e), ee, EEmptyList().with_type(e.type)).with_type(e.type)) elif isinstance(ee, EMap): return self.visit(EMap(EFilter(ee.e, compose(f, ee.transform_function)).with_type(ee.e.type), ee.transform_function).with_type(e.type)) return EFilter(ee, f).with_type(e.type)
def optimized_any_matches(xs, p): if isinstance(xs, EEmptyList): return EFALSE if isinstance(xs, ESingleton): return p.apply_to(xs.e) if isinstance(xs, EMap): return optimized_any_matches(xs.e, compose(p, xs.transform_function)) # exists filter (not-in xs) ys if isinstance(p.body, EUnaryOp) and p.body.op == UOp.Not and isinstance( p.body.e, EBinOp) and p.body.e.op == BOp.In: if p.arg not in free_vars(p.body.e.e2): # er, this only works when xs is a subset of ys return EGt(optimized_len(xs), optimized_len(p.body.e.e2)) if isinstance(p.body, EBinOp) and p.body.op == BOp.Or: return EAny([ optimized_any_matches(xs, ELambda(p.arg, p.body.e1)).with_type(xs.type), optimized_any_matches(xs, ELambda(p.arg, p.body.e2)).with_type(xs.type) ]) if isinstance(xs, EFilter): return optimized_any_matches( xs.e, ELambda(p.arg, EAll([p.body, xs.predicate.apply_to(p.arg)]))) if isinstance(xs, EBinOp) and xs.op == "+": return EAny( [optimized_any_matches(xs.e1, p), optimized_any_matches(xs.e2, p)]) if isinstance(xs, EBinOp) and xs.op == "-": return EAll([ optimized_any_matches(xs.e1, p), ENot(optimized_any_matches(xs.e2, p)) ]) if isinstance(xs, ECond): return optimized_cond(xs.cond, optimized_any_matches(xs.then_branch, p), optimized_any_matches(xs.else_branch, p)).with_type(BOOL) return EUnaryOp(UOp.Exists, EFilter(xs, p).with_type(xs.type)).with_type(BOOL)
def visit_EFilter(self, e): ee = self.visit(e.e) f = self.visit(e.predicate) if f.body == ETRUE: return ee elif f.body == EFALSE: return EEmptyList().with_type(e.type) elif isinstance(ee, EBinOp) and ee.op == "+": return self.visit( EBinOp( EFilter(ee.e1, f).with_type(ee.e1.type), ee.op, EFilter(ee.e2, f).with_type(ee.e2.type)).with_type(e.type)) elif isinstance(ee, ESingleton): return self.visit( ECond(f.apply_to(ee.e), ee, EEmptyList().with_type(e.type)).with_type(e.type)) elif isinstance(ee, EMap): return self.visit( EMap( EFilter(ee.e, compose(f, ee.transform_function)).with_type( ee.e.type), ee.transform_function).with_type(e.type)) return EFilter(ee, f).with_type(e.type)
def optimized_any_matches(xs, p): if isinstance(xs, EEmptyList): return F elif isinstance(xs, ESingleton): return p.apply_to(xs.e) elif isinstance(xs, EMap): return optimized_any_matches(xs.e, compose(p, xs.f)) elif isinstance(xs, EFilter): return optimized_any_matches( xs.e, ELambda(p.arg, EAll([p.body, xs.p.apply_to(p.arg)]))) elif isinstance(xs, EBinOp) and xs.op == "+": return EAny( [optimized_any_matches(xs.e1, p), optimized_any_matches(xs.e2, p)]) elif isinstance(xs, ECond): return optimized_cond(xs.cond, optimized_any_matches(xs.then_branch, p), optimized_any_matches(xs.else_branch, p)).with_type(BOOL) else: return EUnaryOp(UOp.Exists, EFilter(xs, p).with_type(xs.type)).with_type(BOOL)
def optimized_any_matches(xs, p): if isinstance(xs, EEmptyList): return EFALSE if isinstance(xs, ESingleton): return p.apply_to(xs.e) if isinstance(xs, EMap): return optimized_any_matches(xs.e, compose(p, xs.transform_function)) # exists filter (not-in xs) ys if isinstance(p.body, EUnaryOp) and p.body.op == UOp.Not and isinstance(p.body.e, EBinOp) and p.body.e.op == BOp.In: if p.arg not in free_vars(p.body.e.e2): # er, this only works when xs is a subset of ys return EGt( optimized_len(xs), optimized_len(p.body.e.e2)) if isinstance(p.body, EBinOp) and p.body.op == BOp.Or: return EAny([ optimized_any_matches(xs, ELambda(p.arg, p.body.e1)).with_type(xs.type), optimized_any_matches(xs, ELambda(p.arg, p.body.e2)).with_type(xs.type)]) if isinstance(xs, EFilter): return optimized_any_matches(xs.e, ELambda(p.arg, EAll([p.body, xs.predicate.apply_to(p.arg)]))) if isinstance(xs, EBinOp) and xs.op == "+": return EAny([optimized_any_matches(xs.e1, p), optimized_any_matches(xs.e2, p)]) if isinstance(xs, EBinOp) and xs.op == "-": return EAll([ optimized_any_matches(xs.e1, p), ENot(optimized_any_matches(xs.e2, p))]) if isinstance(xs, ECond): return optimized_cond(xs.cond, optimized_any_matches(xs.then_branch, p), optimized_any_matches(xs.else_branch, p)).with_type(BOOL) return EUnaryOp(UOp.Exists, EFilter(xs, p).with_type(xs.type)).with_type(BOOL)
def optimized_best(xs, keyfunc, op, args): argbest = EArgMin if op == "<" else EArgMax elem_type = xs.type.elem_type key_type = keyfunc.body.type if excluded_element(xs, args) is not None: bag, x = excluded_element(xs, args) if all(v not in args for v in free_vars(bag)): heap_type, make_heap = (TMinHeap, EMakeMinHeap) if op == "<" else (TMaxHeap, EMakeMaxHeap) bag = EStateVar(strip_EStateVar(bag)).with_type(bag.type) h = make_heap(bag.e, keyfunc).with_type(heap_type(elem_type, key_type)) for prev_min in optimized_best(bag.e, keyfunc, op, args=args): prev_min = EStateVar(prev_min).with_type(elem_type) heap_peek = EHeapPeek2(EStateVar(h).with_type(h.type)).with_type(elem_type) conds = [optimized_in(x, bag), optimized_eq(x, prev_min)] if isinstance(x, EUnaryOp) and x.op == UOp.The: conds = [optimized_exists(x.e)] + conds yield optimized_cond( EAll(conds), heap_peek, prev_min) if isinstance(xs, EEmptyList): yield construct_value(elem_type) if isinstance(xs, ESingleton): yield xs.e if isinstance(xs, EBinOp) and xs.op == "+": a_ex = optimized_exists(xs.e1) b_ex = optimized_exists(xs.e2) bag_type = TBag(xs.type.elem_type) for a in optimized_best(xs.e1, keyfunc, op, args=args): for b in optimized_best(xs.e2, keyfunc, op, args=args): yield optimized_cond(a_ex, optimized_cond(b_ex, argbest(EBinOp(ESingleton(a).with_type(bag_type), "+", ESingleton(b).with_type(bag_type)).with_type(bag_type), keyfunc).with_type(elem_type), a), optimized_cond(b_ex, b, construct_value(elem_type))) # if isinstance(xs.e1, EStateVar) or isinstance(xs.e2, EStateVar): # sv, other = (xs.e1, xs.e2) if isinstance(xs.e1, EStateVar) else (xs.e2, xs.e1) # sv_best = optimized_best(sv, keyfunc, op, args=args) # yield optimized_cond( # optimized_exists(sv), # argbest(EBinOp(ESingleton(sv_best).with_type(xs.type), "+", other).with_type(xs.type), keyfunc).with_type(elem_type), # optimized_best(other, keyfunc, op, args=args)) # else: # parts = break_sum(xs) # found = EFALSE # best = construct_value(elem_type) # for p in parts: # ex = optimized_exists(p) # best_here = optimized_best(p, keyfunc, op, args=args) # best = optimized_cond(found, # optimized_cond(ex, # optimized_cond(EBinOp(keyfunc.apply_to(best_here), op, keyfunc.apply_to(best)).with_type(BOOL), # best_here, # best), # best), # best_here) # found = EAny([found, ex]) # yield best if isinstance(xs, EMap): for b in optimized_best(xs.e, compose(keyfunc, xs.transform_function), op, args): yield optimized_cond(optimized_exists(xs.e), xs.transform_function.apply_to(b), construct_value(elem_type)) if isinstance(xs, EStateVar) and not any(v in args for v in free_vars(keyfunc)): yield EStateVar(argbest(xs.e, keyfunc).with_type(elem_type)).with_type(elem_type) if isinstance(xs, ECond): for a in optimized_best(xs.then_branch, keyfunc, op, args=args): for b in optimized_best(xs.else_branch, keyfunc, op, args=args): yield optimized_cond(xs.cond, a, b) if isinstance(xs, EUnaryOp) and xs.op == UOp.Distinct: yield from optimized_best(xs.e, keyfunc, op, args=args) # if isinstance(xs, EFilter): # yield optimized_cond( # xs.predicate.apply_to(optimized_best(xs.e, keyfunc, op, args=args)), # optimized_best(xs.e, keyfunc, op, args=args), # argbest(xs, keyfunc).with_type(elem_type)) yield argbest(xs, keyfunc).with_type(elem_type)
def optimized_best(xs, keyfunc, op, args): argbest = EArgMin if op == "<" else EArgMax elem_type = xs.type.t key_type = keyfunc.body.type if excluded_element(xs, args) is not None: bag, x = excluded_element(xs, args) if all(v not in args for v in free_vars(bag)): heap_type, make_heap = (TMinHeap, EMakeMinHeap) if op == "<" else ( TMaxHeap, EMakeMaxHeap) bag = EStateVar(strip_EStateVar(bag)).with_type(bag.type) h = make_heap(bag.e, keyfunc).with_type(heap_type(elem_type, key_type)) prev_min = EStateVar( optimized_best( bag.e, keyfunc, op, args=args).with_type(elem_type)).with_type(elem_type) heap_peek = EHeapPeek2( EStateVar(h).with_type(h.type), EStateVar(ELen(bag.e)).with_type(INT)).with_type(elem_type) return optimized_cond( EAll([optimized_in(x, bag), optimized_eq(x, prev_min)]), heap_peek, prev_min) if isinstance(xs, EEmptyList): return construct_value(elem_type) if isinstance(xs, ESingleton): return xs.e if isinstance(xs, EBinOp) and xs.op == "+": if isinstance(xs.e1, EStateVar) or isinstance(xs.e2, EStateVar): sv, other = (xs.e1, xs.e2) if isinstance(xs.e1, EStateVar) else (xs.e2, xs.e1) sv_best = optimized_best(sv, keyfunc, op, args=args) return optimized_cond( optimized_exists(sv), argbest( EBinOp(ESingleton(sv_best).with_type(xs.type), "+", other).with_type(xs.type), keyfunc).with_type(elem_type), optimized_best(other, keyfunc, op, args=args)) else: parts = break_sum(xs) found = F best = construct_value(elem_type) for p in parts: ex = optimized_exists(p) best_here = optimized_best(p, keyfunc, op, args=args) best = optimized_cond( found, optimized_cond( ex, optimized_cond( EBinOp(keyfunc.apply_to(best_here), op, keyfunc.apply_to(best)).with_type(BOOL), best_here, best), best), best_here) found = EAny([found, ex]) return best if isinstance(xs, EMap): return xs.f.apply_to( optimized_best(xs.e, compose(keyfunc, xs.f), op, args)) if isinstance(xs, EStateVar) and not any(v in args for v in free_vars(keyfunc)): return EStateVar(argbest( xs.e, keyfunc).with_type(elem_type)).with_type(elem_type) if isinstance(xs, ECond): return optimized_cond( xs.cond, optimized_best(xs.then_branch, keyfunc, op, args=args), optimized_best(xs.else_branch, keyfunc, op, args=args)) if isinstance(xs, EUnaryOp) and xs.op == UOp.Distinct: return optimized_best(xs.e, keyfunc, op, args=args) # if isinstance(xs, EFilter): # return optimized_cond( # xs.p.apply_to(optimized_best(xs.e, keyfunc, op, args=args)), # optimized_best(xs.e, keyfunc, op, args=args), # argbest(xs, keyfunc).with_type(elem_type)) return argbest(xs, keyfunc).with_type(elem_type)
def optimized_best(xs, keyfunc, op, args): argbest = EArgMin if op == "<" else EArgMax elem_type = xs.type.elem_type key_type = keyfunc.body.type if excluded_element(xs, args) is not None: bag, x = excluded_element(xs, args) if all(v not in args for v in free_vars(bag)): heap_type, make_heap = (TMinHeap, EMakeMinHeap) if op == "<" else ( TMaxHeap, EMakeMaxHeap) bag = EStateVar(strip_EStateVar(bag)).with_type(bag.type) h = make_heap(bag.e, keyfunc).with_type(heap_type(elem_type, key_type)) for prev_min in optimized_best(bag.e, keyfunc, op, args=args): prev_min = EStateVar(prev_min).with_type(elem_type) heap_peek = EHeapPeek2(EStateVar(h).with_type( h.type)).with_type(elem_type) conds = [optimized_in(x, bag), optimized_eq(x, prev_min)] if isinstance(x, EUnaryOp) and x.op == UOp.The: conds = [optimized_exists(x.e)] + conds yield optimized_cond(EAll(conds), heap_peek, prev_min) if isinstance(xs, EEmptyList): yield construct_value(elem_type) if isinstance(xs, ESingleton): yield xs.e if isinstance(xs, EBinOp) and xs.op == "+": a_ex = optimized_exists(xs.e1) b_ex = optimized_exists(xs.e2) bag_type = TBag(xs.type.elem_type) for a in optimized_best(xs.e1, keyfunc, op, args=args): for b in optimized_best(xs.e2, keyfunc, op, args=args): yield optimized_cond( a_ex, optimized_cond( b_ex, argbest( EBinOp( ESingleton(a).with_type(bag_type), "+", ESingleton(b).with_type(bag_type)).with_type( bag_type), keyfunc).with_type(elem_type), a), optimized_cond(b_ex, b, construct_value(elem_type))) # if isinstance(xs.e1, EStateVar) or isinstance(xs.e2, EStateVar): # sv, other = (xs.e1, xs.e2) if isinstance(xs.e1, EStateVar) else (xs.e2, xs.e1) # sv_best = optimized_best(sv, keyfunc, op, args=args) # yield optimized_cond( # optimized_exists(sv), # argbest(EBinOp(ESingleton(sv_best).with_type(xs.type), "+", other).with_type(xs.type), keyfunc).with_type(elem_type), # optimized_best(other, keyfunc, op, args=args)) # else: # parts = break_sum(xs) # found = EFALSE # best = construct_value(elem_type) # for p in parts: # ex = optimized_exists(p) # best_here = optimized_best(p, keyfunc, op, args=args) # best = optimized_cond(found, # optimized_cond(ex, # optimized_cond(EBinOp(keyfunc.apply_to(best_here), op, keyfunc.apply_to(best)).with_type(BOOL), # best_here, # best), # best), # best_here) # found = EAny([found, ex]) # yield best if isinstance(xs, EMap): for b in optimized_best(xs.e, compose(keyfunc, xs.transform_function), op, args): yield optimized_cond(optimized_exists(xs.e), xs.transform_function.apply_to(b), construct_value(elem_type)) if isinstance(xs, EStateVar) and not any(v in args for v in free_vars(keyfunc)): yield EStateVar(argbest( xs.e, keyfunc).with_type(elem_type)).with_type(elem_type) if isinstance(xs, ECond): for a in optimized_best(xs.then_branch, keyfunc, op, args=args): for b in optimized_best(xs.else_branch, keyfunc, op, args=args): yield optimized_cond(xs.cond, a, b) if isinstance(xs, EUnaryOp) and xs.op == UOp.Distinct: yield from optimized_best(xs.e, keyfunc, op, args=args) # if isinstance(xs, EFilter): # yield optimized_cond( # xs.predicate.apply_to(optimized_best(xs.e, keyfunc, op, args=args)), # optimized_best(xs.e, keyfunc, op, args=args), # argbest(xs, keyfunc).with_type(elem_type)) yield argbest(xs, keyfunc).with_type(elem_type)