Пример #1
0
 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)
Пример #2
0
 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)
Пример #3
0
 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)
Пример #4
0
 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)
Пример #5
0
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)
Пример #6
0
 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)
Пример #7
0
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)
Пример #8
0
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)
Пример #9
0
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)
Пример #10
0
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)
Пример #11
0
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)