Ejemplo n.º 1
0
def compress_tiles(tiled_subpme):
    compressed = []
    for tiles in tiled_subpme:
        compressed.append([])
        i = 0
        while i < len(tiles):
            #for i, tile in enumerate( tiles ):
            tile = tiles[i]
            lhs, rhs = tile.get_children()
            if isinstance(rhs, Predicate):
                compressed[-1].append(copy.deepcopy(tile))
                i += 1
                continue
            replaced = False
            for j, other_tile in enumerate(tiles[i + 1:], start=i + 1):
                olhs, orhs = other_tile.get_children()
                lhs_ch = lhs.get_children()[0]
                if contains(orhs, lhs_ch):
                    new_other = copy.deepcopy(other_tile)
                    #new_other = replace( new_other, [RewriteRule(lhs_ch, Replacement(rhs))] )
                    new_other.children[1] = replace(
                        new_other.rhs(),
                        [RewriteRule(lhs_ch, Replacement(rhs))])
                    tiles[j] = new_other
                    replaced = True
                # if tile lhs = f(rhs) and other_tile overwrites lhs (lhs = f(lhs))
                # stop replacing with "old" lhs
                if lhs_ch in olhs.children:
                    break
            if not replaced:
                compressed[-1].append(copy.deepcopy(tile))
            i += 1
    return compressed
Ejemplo n.º 2
0
def code_dispatcher(node, out):
    global indent_level, indent_char
    indent = indent_level * indent_char

    if isinstance(node, lpla.function):
        code_function(node, out)
    elif isinstance(node, lpla.declare):
        code_declare(node, out)
    elif isinstance(node, Equal):
        node = replace(node, trsm_patterns)
        if isinstance(node, str):
            print(indent + node + ";", file=out)
        else:
            print(indent + click2matlab(node) + ";", file=out)
    elif isinstance(node, lpla.partition):
        code_partition(node, out)
    elif isinstance(node, lpla.repartition):
        code_repartition(node, out)
    elif isinstance(node, lpla.progress):
        code_progress(node, out)
    elif isinstance(node, lpla.combine):
        code_combine(node, out)
    elif isinstance(node, lpla._while):
        code_while(node, out)
    elif isinstance(node, lpla.spacing):
        code_spacing(node, out)
Ejemplo n.º 3
0
def update_TOE(rule):
    for prop in TOE_properties:
        for _expr in TOE[prop]:
            #for rule in rewrite_rules:
            expr = copy.deepcopy(_expr)
            expr = replace(expr, [rule])
            new = copy.deepcopy(expr)
            new = simplify(to_canonical(new))
            TOE.set_property(prop, new)
Ejemplo n.º 4
0
 def tile( self, tree, node, match_dict ):
     _T = TOS.new_temp()
     temp = Symbol("T" + str(_T))
     temp.set_property( properties.TEMPORARY )
     #
     if isinstance( node, Predicate ):
         if node == tree:
             print( "[Warning] If predicate has multiple outputs, may break if not careful from caller" )
         return Equal([ NList([ temp ]), copy.deepcopy( node ) ]), \
                 replace( tree, [RewriteRule( copy.deepcopy( node ), Replacement(temp) )] )
     else:
         tile_expr = self.create_tile( match_dict )
         propagate_properties( tile_expr, temp )
         propagate_st_info( tile_expr, temp )
         ## [FIXME] Quick and dirty test
         #if isUpperTriangular( tile_expr ):
             #print( temp, "is upper triangular" )
             #temp.set_property( properties.UPPER_TRIANGULAR )
         return Equal([ NList([ temp ]), self.create_tile( match_dict ) ]), \
                 replace( tree, [self.create_rewrite_rule( match_dict, temp )] )
Ejemplo n.º 5
0
 def _PassStorage(st):
     if isinstance(st, lpla._while):
         for s in st.body:
             _PassStorage(s)
     elif isinstance(st, Equal):
         symbols = []
         for n in st.iterate_preorder():
             # Zero has no st_info...
             if isinstance(n, Zero):
                 pass
             elif isinstance(n, Symbol) and n.st_info[1] != n:
                 n_st = n.st_info[1]
                 n_st.st_info = n.st_info
                 # E.g., in Cholesky, n is L_11, and n_st is A_11
                 #if n.isLowerTriangular() and not n_st.isLowerTriangular():
                 #symbols.append( RewriteRule( n, Replacement(tril(n_st)) ) )
                 #elif n.isUpperTriangular() and not n_st.isUpperTriangular():
                 #symbols.append( RewriteRule( n, Replacement(triu(n_st)) ) )
                 #else:
                 symbols.append(RewriteRule(n, Replacement(n_st)))
         replace(st, symbols)
Ejemplo n.º 6
0
 def opt_copy_propagation(self):
     for i, st in enumerate(self.statements):
         if isinstance(st, Equal):
             lhs, rhs = st.children
             lhs = lhs.children
             if len(lhs) == 1 and lhs[0].isTemporary() and isinstance(
                     st.rhs(), Symbol):
                 for oth_st in self.statements[i + 1:]:
                     if not isinstance(
                             oth_st, Equal
                     ):  #[CHECK] Careful. Not the case, but generally speaking could be some part/repart
                         continue
                     oth_lhs, oth_rhs = oth_st.lhs(), oth_st.rhs()
                     if contains(oth_rhs, lhs[0]):
                         #\ and not (isinstance( oth_rhs, Predicate ) and pm.DB[oth_rhs.name].overwrite): #[FIXME] Can be less restrictive
                         new_rhs = replace(
                             oth_rhs,
                             [RewriteRule(lhs[0], Replacement(rhs))])
                         oth_st.children[1] = new_rhs
                     if oth_lhs.children[0] == lhs[0] or oth_lhs == rhs:
                         break
Ejemplo n.º 7
0
    def partition(self):
        self.basic_partitionings = dict()
        self.partitionings = dict()
        rewrite_rules = []
        for operand in self.operands:
            op_name = operand.get_name()
            # For code generation
            #part = partition_shape( operand, self.part_shape[op_name] )
            part = partition_shape_with_storage(operand,
                                                self.part_shape[op_name])
            self.basic_partitionings[op_name] = part
            #
            part = partition(operand, self.part_shape[op_name],
                             operand.get_properties())
            self.partitionings[op_name] = part
            #
            rewrite_rules.append(RewriteRule(operand, Replacement(part)))

        self.partitioned_postcondition = \
            [replace( copy.deepcopy(eq), rewrite_rules ) for eq in self.equation]

        print("* Partitioned postcondition")
        for eq in self.partitioned_postcondition:
            print("*    ", eq)
Ejemplo n.º 8
0
def _checkPredicateOverwrite(statement):
    lhs = statement.lhs()
    rhs = statement.rhs()
    if not isinstance(rhs, Predicate):
        rhs_ops = [
            node for node in rhs.iterate_preorder()
            if isinstance(node, Symbol)
        ]
        tmp_ops = [op for op in rhs_ops if op.isTemporary()]
        if len(tmp_ops
               ) == 1:  # [FIXME] Quick and dirty to play with temporaries
            tmp = tmp_ops[0]
            if lhs.children[0].size == tmp.size:
                if not lhs.children[0].isTemporary():
                    overwrites = False
                    for op in rhs_ops:
                        try:
                            overwrites = lhs.children[0].st_info[
                                1] == op.st_info[1]
                        except AttributeError:
                            pass
                        if overwrites: break
                    if not overwrites:
                        statements = []
                        statements.append(Equal([NList(lhs.children), tmp]))
                        statement.children[1] = replace(
                            copy.deepcopy(rhs),
                            [RewriteRule(tmp, Replacement(lhs.children[0]))])
                        statements.append(statement)
                        return statements
        else:
            # TRSM 2x2 ...
            pass
        return [statement]
    if not pm.DB[rhs.name].overwrite:  # []
        return [statement]

    statements = []
    # [FIXME] Assumes one single operands get overwritten. Will break in the future
    already_copied = []
    for inp, out in pm.DB[rhs.name].overwrite:
        if inp in already_copied:
            continue
        already_copied.append(inp)
        #
        if rhs.children[inp] != lhs.children[
                out]:  # [FIXME] All should have st_into
            try:
                overwrites = lhs.children[out].st_info[1] == rhs.children[
                    inp].st_info[1]
            except AttributeError:
                overwrites = False
            if overwrites:
                statements.append(statement)  #[FIXME] Gosh...
                continue
            inpop = rhs.children[inp]
            outop = lhs.children[out]
            if inpop.isTemporary() or inpop.isInput():
                # if multiple outputs overwrite input (e.g., LU)
                if len([o for i, o in pm.DB[rhs.name].overwrite if i == inp
                        ]) > 1:
                    try:
                        outop = TOS._TOS[outop.st_info[1].name][
                            0]  # LU  (ABR = T3; [LBR,UBR] = LU(ABR))
                    except:
                        pass
                    outop.st_info = (None, outop)
                #
                statements.append(Equal([NList([outop]), inpop]))
                rhs.children[inp] = outop
                statements.append(statement)
            else:
                lhs.children[out] = rhs.children[inp]
                statements.append(statement)
                statements.append(Equal([NList([inpop]), outop]))
        else:
            statements.append(statement)
    return statements
Ejemplo n.º 9
0
    def generate_predicate_before(
            self, pme, trav, linv,
            linv_obj):  # [TODO] Cleanup, no need for linv AND linv_obj
        new = [copy.deepcopy(expr) for expr in itertools.chain(*linv)]
        # Repartition
        reparts = dict()
        repart_rules = []
        for op in linv_obj.linv_operands:
            part = linv_obj.linv_operands_basic_part[op.get_name()]
            # [CHECK] _shape or not? Regular one needed for inheritance
            repart = repartition(op, part.shape, trav[op.get_name()])
            #
            #repart_shape = {(1,1):(1,1), (1,2):(1,3), (2,1):(3,1), (2,2):(3,3)}[part.shape]
            #repart = repartition_shape( op, repart_shape )
            #repart = repart_group( repart, repart_shape, trav[op.get_name()] )
            #
            for part_op, repart_op in zip(itertools.chain(*part),
                                          itertools.chain(*repart)):
                repart_rules.append(
                    RewriteRule(part_op, Replacement(repart_op)))
            reparts[op.get_name()] = repart
        # Apply repartitionings
        new = [replace(expr, repart_rules) for expr in new]

        # Explicit functions to BlockedExpression
        #  First flatten args, then replace
        for expr in new:
            lhs, rhs = expr.get_children()
            if isinstance(rhs, Predicate):
                for i, arg in enumerate(rhs.get_children()):
                    #rhs.set_children( i, flatten_blocked_operation(arg) )
                    rhs.set_children(i, flatten_blocked_operation_click(arg))
        new = [replace(expr, known_pmes) for expr in new]

        # Operators applied to BlockedExpression, into BlockedExpressions
        for expr in new:
            if isinstance(expr, BlockedExpression):
                continue
            _, rhs = expr.get_children()
            #print( rhs ) # [TODO] Maybe "Sylv(...)"!!!
            #rhs = flatten_blocked_operation( rhs )
            rhs = flatten_blocked_operation_click(rhs)
            expr.set_children(1, rhs)

        # Flatten left-hand sides of the previous type of expressions
        for expr in new:
            if isinstance(expr, BlockedExpression):
                continue
            lhs, rhs = expr.get_children()
            new_lhs = []
            for out in lhs:
                if isinstance(out, Symbol):  # this is a temporary one
                    out.size = rhs.get_size()
                    #part = partition_shape( out, rhs.shape )
                    part = partition_shape(out, tuple(rhs.shape))
                    new_lhs.append(part)
                else:
                    new_lhs.append(out)
            lhs = BlockedExpression(map_thread(NList, new_lhs, 2), (0, 0),
                                    rhs.shape)
            expr.set_children(0, lhs)
        # Flatten the last type of expressions
        final = []
        for expr in new:
            if isinstance(expr, BlockedExpression):
                final.extend([
                    simplify(to_canonical(eq)) for eq in itertools.chain(*expr)
                ])
            else:
                lhs, rhs = expr.get_children()
                final.extend([
                    simplify(to_canonical(eq))
                    for eq in itertools.chain.from_iterable(
                        map_thread(Equal, [lhs, rhs], 2))
                ])
        final = filter_zero_zero(final)
        # remove expressions of the type " B_10^T = ..." (e.g., in symv)"
        _final = final
        final = []
        for expr in _final:
            lhs, rhs = expr.children
            lhs = lhs.children
            # [FIXME] == 1 only to make sure it does not affect other cases.
            # Just want to let them break and study them in the future
            if len(lhs) == 1 and (not isOperand(lhs[0]) or lhs[0].isZero()):
                continue
            final.append(expr)
        #
        # expand in terms of input parts
        #
        #expand_rules = list(itertools.chain(*self.expr_to_rule_lhs_rhs( final )))
        #for expr in final:
        #expr.children[1] = simplify(to_canonical(replace_all(copy.deepcopy(expr.children[1]), expand_rules)))
        #
        # Print and return
        #
        for expr in final:
            print("*   ", expr)

        return (reparts, final)
Ejemplo n.º 10
0
    def find_updates_v2(self, before, after):
        # If a part is (partially) computed in the before and
        #   does not appear in the after or
        # going from before to after requires undoing some computation
        # it is potentially unstable, and more expensive: ignore
        dict_bef = dict([(str(u.get_children()[0]), u) for u in before])
        dict_aft = dict([(str(u.get_children()[0]), u) for u in after])
        ignore = False
        quadrant = None
        for k, v in dict_bef.items():
            if k not in dict_aft:
                ignore = True
                break
            else:
                rules = self.expr_to_rule_rhs_lhs([v])
                rules = list(itertools.chain(*rules))
                expr_copy = copy.deepcopy(dict_aft[k])
                t = replace(expr_copy, rules)
                #if v == replace( expr_copy, rules ):
                if dict_aft[k] == t:
                    ignore = True
                    break
        if ignore:
            print("[INFO] Skipping invariant: %s" % reason)
            return None
        #
        # Wrap outputs for before and after
        WrapBefOut = WrapOutBef
        for u in before:
            u.children[0] = NList([WrapBefOut(l) for l in u.children[0]])
        #
        wrap_rules_after = []
        for u in after:
            u.children[0] = NList([WrapOutAft(l) for l in u.children[0]])
        # replace before in after
        wrap_rules_before = []
        for u in before:
            print(u)
            lhs, rhs = u.get_children()
            if len(lhs.children) > 1:
                continue
            rules = self.expr_to_rule_rhs_lhs([u])
            wrap_rules_before.append(list(itertools.chain(*rules)))
        #
        for i, rule in enumerate(reversed(wrap_rules_before)):
            idx = len(wrap_rules_before) - i - 1
            for j in range(idx - 1, -1, -1):
                for _rule in rule:
                    _rule.pattern = replace_all(_rule.pattern,
                                                wrap_rules_before[j])
        wrap_rules_before = list(itertools.chain(*wrap_rules_before))
        #
        for u in after:
            _, rhs = u.get_children()
            u.children[1] = simplify(
                to_canonical(replace_all(copy.deepcopy(rhs),
                                         wrap_rules_before)))
        # replace after in after
        done = False
        while not done:
            # replace after in after
            wrap_rules_after = []
            for u in after:
                lhs, rhs = u.get_children()
                if len(lhs.children) > 1:
                    wrap_rules_after.append([])
                    continue
                rules = self.expr_to_rule_rhs_lhs([u])
                wrap_rules_after.append(list(itertools.chain(*rules)))
            #
            after_top = [copy.deepcopy(u) for u in after]
            for i, u in enumerate(after):
                _, rhs = u.get_children()
                rules = list(
                    itertools.chain.from_iterable(wrap_rules_after[:i] +
                                                  wrap_rules_after[i + 1:]))
                u.children[1] = simplify(
                    to_canonical(replace_all(copy.deepcopy(rhs), rules)))
            done = True
            for top, bot in zip(after_top, after):
                if top != bot:
                    done = False
                    break
        # [TODO] Multiple lhss, won't work
        updates = []
        for u in after:
            lhs, rhs = u.get_children()
            lhs = lhs.children[0]  # NList[op] -> op
            if isinstance(rhs, WrapBefOut) and isinstance(lhs, WrapOutAft) and \
                    matchq(lhs.children[0], rhs.children[0]):
                continue
            updates.append(u)
        #
        tiled_updates = []
        for u in updates:
            print("*   ", u)
            tilings = list(tile_expr(u))
            if len(tilings) > 1:
                print("[WARNING] Multiple (%d) tilings for expression %s" %
                      (len(tilings), u))
                print("          Discarding all but one")
            tiled_updates.extend(tilings[0])
        tiled_updates = sort(tiled_updates)
        print("* Tiled update")
        for t in tiled_updates:
            print("*   ", t)

        # Drop WrapOutBef's
        # Drop WrapOutAft's
        s = PatternDot("s")
        updates = []
        for u in tiled_updates:
            u = replace_all(
                u, [RewriteRule(WrapOutAft(s), Replacement(lambda d: d["s"]))])
            u = replace_all(
                u, [RewriteRule(WrapOutBef(s), Replacement(lambda d: d["s"]))])
            updates.append(u)

        return updates
Ejemplo n.º 11
0
    def find_updates(self, before, after):
        # If a part is (partially) computed in the before and
        #   does not appear in the after or
        # going from before to after requires undoing some computation
        # it is potentially unstable, and more expensive: ignore
        try:
            before_finputs = self.express_in_terms_of_input(before)
            after_finputs = self.express_in_terms_of_input(after)
        except:
            # [TODO] In LU's variant 5, parts of A appear as lhs's
            return None
        #
        dict_bef = dict([(str(u.get_children()[0]), u)
                         for u in before_finputs])
        dict_aft = dict([(str(u.get_children()[0]), u) for u in after_finputs])
        same = []
        ignore = False
        for k, v in dict_bef.items():
            if k in dict_aft and matchq(v, dict_aft[k]):
                same.extend(v.children[0].children)
            if k not in dict_aft:
                ignore = True
                reason = "%s not in %s" % (k, dict_aft.keys())
                break
            else:
                rules = self.expr_to_rule_rhs_lhs([v])
                rules = list(itertools.chain(*rules))
                expr_copy = copy.deepcopy(dict_aft[k])
                t = replace(expr_copy, rules)
                #if v == replace( expr_copy, rules ):
                if dict_aft[k] == t:
                    ignore = True
                    reason = "%s would require undoing job" % k
                    break
        if ignore:
            print("[INFO] Skipping invariant: %s" % reason)
            return None
        #
        # Wrap outputs for before and after
        WrapBefOut = WrapOutBef
        lhss = []
        for u in before:
            lhss.extend(u.children[0])
            u.children[0] = NList([WrapBefOut(l) for l in u.children[0]])
        for u in before:
            u.children[1] = replace(
                u.children[1],
                [RewriteRule(l, Replacement(WrapBefOut(l))) for l in lhss])
        #
        lhss = []
        for u in after:
            lhss.extend(u.children[0])
            u.children[0] = NList([WrapOutAft(l) for l in u.children[0]])
        wrap_rules_after = \
                [
                    RewriteRule(l, Replacement(WrapBefOut(l))) if l in same else
                    RewriteRule(l, Replacement(WrapOutAft(l))) for l in lhss
                ]
        for u in after:
            u.children[1] = replace(u.children[1], wrap_rules_after)
        # replace before in before
        wrap_rules_before = []
        for u in before:
            lhs, rhs = u.get_children()
            #if len(lhs.children) > 1:
            #wrap_rules_before.append([])
            #continue
            rules = self.expr_to_rule_rhs_lhs([u])
            wrap_rules_before.append(list(itertools.chain(*rules)))
        #
        new_rules = []
        for i, rules in enumerate(wrap_rules_before):
            new_rules.append([])
            for rule in rules:
                new_r = copy.deepcopy(rule)
                new_r.pattern = replace_all(
                    new_r.pattern,
                    list(
                        itertools.chain.from_iterable(wrap_rules_before[:i] +
                                                      wrap_rules_before[i +
                                                                        1:])))
                if new_r.pattern != rule.pattern:
                    new_rules[-1].append(new_r)
        for r1, r2 in zip(new_rules, wrap_rules_before):
            r2.extend(r1)
        #
        wrap_rules_before = list(itertools.chain(*wrap_rules_before))
        done = False
        while not done:
            after_top = [copy.deepcopy(u) for u in after]
            for i, u in enumerate(after):
                _, rhs = u.get_children()
                u.children[1] = simplify(
                    to_canonical(
                        replace_all(copy.deepcopy(rhs), wrap_rules_before)))
            done = True
            for top, bot in zip(after_top, after):
                if top != bot:
                    done = False
                    break
        # replace after in after
        done = False
        while not done:
            # replace after in after
            wrap_rules_after = []
            for u in after:
                lhs, rhs = u.get_children()
                #if len(lhs.children) > 1:
                #wrap_rules_after.append([])
                #continue
                rules = self.expr_to_rule_rhs_lhs([u])
                wrap_rules_after.append(list(itertools.chain(*rules)))
            #
            after_top = [copy.deepcopy(u) for u in after]
            for i, u in enumerate(after):
                _, rhs = u.get_children()
                rules = list(
                    itertools.chain.from_iterable(wrap_rules_after[:i] +
                                                  wrap_rules_after[i + 1:]))
                u.children[1] = simplify(
                    to_canonical(replace_all(copy.deepcopy(rhs), rules)))
            done = True
            for top, bot in zip(after_top, after):
                if top != bot:
                    done = False
                    break
        # [TODO] Multiple lhss, won't work
        updates = []
        for u in after:
            lhs, rhs = u.get_children()
            if len(lhs.children) == 1:
                lhs = lhs.children[0]  # NList[op] -> op
                if isinstance(rhs, WrapBefOut) and isinstance(lhs, WrapOutAft) and \
                        matchq(lhs.children[0], rhs.children[0]):
                    continue
            elif not isinstance(rhs,
                                NList):  # multiple outputs/predicate in rhs,
                # but not complete (otherwise it would be NList)
                pass
            else:
                to_skip = True
                for l, r in zip(lhs.children, rhs.children):
                    if not( isinstance(r, WrapBefOut) and isinstance(l, WrapOutAft) and \
                            matchq(l.children[0], r.children[0]) ):
                        to_skip = False
                        break
                if to_skip:
                    continue
            updates.append(u)
        #
        tiled_updates = []
        for u in updates:
            print("*   ", u)
            tilings = list(tile_expr(u))
            if len(tilings) > 1:
                print("[WARNING] Multiple (%d) tilings for expression %s" %
                      (len(tilings), u))
                print("          Discarding all but one")
            tiled_updates.extend(tilings[0])
        tiled_updates = sort(tiled_updates)
        print("* Tiled update")
        for t in tiled_updates:
            print("*   ", t)

        # Drop WrapOutBef's
        # Drop WrapOutAft's
        s = PatternDot("s")
        updates = []
        for u in tiled_updates:
            u = replace_all(
                u, [RewriteRule(WrapOutAft(s), Replacement(lambda d: d["s"]))])
            u = replace_all(
                u, [RewriteRule(WrapOutBef(s), Replacement(lambda d: d["s"]))])
            updates.append(u)

        return updates
Ejemplo n.º 12
0
def flatten_blocked_operation_click( expr ):
    PD = PatternDot("PD")
    rule = RewriteRule( WrapOutBef( PD ), \
                        Replacement(lambda d: BlockedExpression( map_thread( WrapOutBef, [d["PD"]], 2 ), d["PD"].size, d["PD"].shape)) )
    expr = replace( copy.deepcopy(expr), [rule] )
    return flatten_blocked_operation( expr ) 
Ejemplo n.º 13
0
    def solve_equations(self):
        dist = self.distributed_partitioned_postcondition
        # Update TOE
        for eq in dist.flatten_children():
            for subeq in eq:
                lhs, rhs = subeq.get_children()
                update_TOE(RewriteRule(lhs, Replacement(rhs)))
                update_TOE(RewriteRule(rhs, Replacement(lhs)))
        # Collect all output parts to be computed
        basic_part = self.basic_partitionings
        basic_part = self.partitionings  #[TODO] Ok?
        all_outputs = []
        for op in self.operands:
            if op.isOutput():
                all_outputs.extend([
                    node
                    for node in basic_part[op.get_name()].iterate_preorder()
                    if isinstance(node, Symbol)
                ])

        # Iterate until PME is solved
        subeqs_to_solve = dist.flatten_children()
        subeqs_to_solve = filter_zero_zero(subeqs_to_solve)
        subeqs_solved = []
        solved_outputs = set([
            ""
        ])  # any initialization that cannot render the equality below true
        solved = False
        #
        while not solved:
            for eq in subeqs_to_solve:
                new = replace(copy.deepcopy(eq), self.known_ops)
                if isinstance(new, Equal):
                    lhs, rhs = new.get_children()
                    # Set input property
                    if all([isinstance(elem, Symbol) for elem in lhs]):
                        if isinstance(rhs, Predicate):
                            rhs.set_property(INPUT)  # SOLVED?
                        for op in lhs:
                            op.set_property(INPUT)  # SOLVED?
                        subeqs_solved.append(new)
                    else:
                        #print( "Can it be?" )
                        # Yes, e.g., trans(X_BL) in lyapunov
                        #raise Exception
                        pass
            cur_solved_outputs = set(
                [op.get_name() for op in all_outputs if isInput(op)])
            #print( "SOLVED:", cur_solved_outputs )
            if solved_outputs == cur_solved_outputs:
                print("")
                print(
                    "[WARNING] PME Generation is stuck - Trying recursive instance"
                )
                print("")
                minimum = (100000, 100000)
                subeq = None
                for eq in subeqs_to_solve:
                    unks = []
                    cnt = 0
                    for node in eq.iterate_preorder():
                        cnt += 1
                        if isinstance(node, Symbol) and node.isOutput(
                        ) and node not in unks:
                            unks.append(node)
                    if (len(unks), cnt) < minimum:
                        subeq = eq
                        minimum = (len(unks), cnt)
                from NestedInstance import rec_instance
                ((md_name, md_data), new_patts,
                 new_pmes) = rec_instance(subeq.children[0])
                self.known_pmes.extend(new_pmes)
                print("NPMES:", len(new_pmes))
                for patt in new_patts:
                    self.known_ops.append(patt)
                pm.DB[md_name] = md_data
                #raise Exception
            solved_outputs = cur_solved_outputs
            if all([isInput(op) or op.isZero() for op in all_outputs]):
                solved = True
            else:
                new_to_solve = []
                for eq in subeqs_to_solve:
                    if not isinstance( eq, Equal ) and \
                            len([op for op in eq.iterate_preorder() if isinstance(op, Symbol) and isOutput(op)]) != 0:
                        new_to_solve.append(eq)
                subeqs_to_solve = [
                    simplify(to_canonicalIO(eq))._cleanup()
                    for eq in new_to_solve
                ]
        self.solved_subequations = subeqs_solved
        # Replace rhs with lhs if they appear as subexpressions of other rhss
        #
        # Create replacements when suited
        reuse_rules = []
        for i, eq in enumerate(subeqs_solved):
            eq_rules = []
            lhs, rhs = eq.children
            if not isinstance(rhs, Predicate) and rhs.get_head() not in (
                    Minus, Transpose, Inverse):
                lhs_sym = lhs.children[0]
                t = PatternStar("t")
                l = PatternStar("l")
                r = PatternStar("r")
                repl_f = (lambda lhs_sym: lambda d: Plus(
                    [d["t"], Times([d["l"], lhs_sym, d["r"]])]))(lhs_sym)
                eq_rules.append(
                    RewriteRule(Plus([t, Times([l, rhs, r])]),
                                Replacement(repl_f)))
                # A - B C in  -L B C R + L A R  (minus pushed all the way to the left)
                if len(rhs.children) > 1:
                    repl_f = (lambda lhs_sym: lambda d: Times(
                        [Minus([lhs_sym])] + d["r"].children))(lhs_sym)
                    eq_rules.append(
                        RewriteRule(
                            Times([
                                Minus([rhs.children[0]]), *rhs.children[1:], r
                            ]), Replacement(repl_f)))
            reuse_rules.append((i, eq_rules))

        # Replace
        self.solved_subequations = []
        for i, eq in enumerate(subeqs_solved):
            rules = [r for j, r in reuse_rules if i != j]
            self.solved_subequations.append(
                replace_all(eq, list(itertools.chain(*rules))))

        # [TODO] Add T to operands and bind dimensions
        #self.bind_temporaries( )
        # Reset outputs
        for op in solved_outputs:
            TOS[op][0].set_property(OUTPUT)

        print("* PME ")
        for eq in self.solved_subequations:
            print("*    ", eq)
Ejemplo n.º 14
0
    def learn_pattern(self):
        inops = [op for op in self.operands if op.isInput()]
        outops = [op for op in self.operands if op.isOutput()]
        # pattern
        predicate_inops = []
        predicate_outops = []
        for op in self.operands:
            rewrite_predicate_ops = []
            basic_part = self.basic_partitionings[op.get_name()]
            for part_op in itertools.chain(*basic_part):
                rewrite_predicate_ops.append(
                    RewriteRule(part_op,
                                Replacement(PatternDot(part_op.get_name()))))
            new = BlockedExpression(
                copy.deepcopy(self.basic_partitionings[op.get_name()]),
                op.get_size(), basic_part.shape)
            if op.isInput():
                predicate_inops.append(replace(new, rewrite_predicate_ops))
            else:
                predicate_outops.append(replace(new, rewrite_predicate_ops))
        pattern = Equal([
            NList(predicate_outops),
            Predicate(self.name, predicate_inops,
                      [op.get_size() for op in outops])
        ])
        # replacement
        # [TODO] Tuple for get_size
        #basic_parts = self.basic_partitionings
        basic_parts = self.partitionings
        lhss = map_thread(NList, [basic_parts[op.get_name()] for op in outops],
                          2)

        # [TODO] This is a fix for lu (maybe coup sylv as well).
        #        Generalize and clean up
        for i, row in enumerate(lhss):
            for j, cell in enumerate(row):
                cell = replace(cell, [
                    RewriteRule(
                        (NList([PatternPlus("PP"),
                                PatternDot("PD")
                                ]), Constraint(lambda d: isZero(d["PD"]))),
                        Replacement(lambda d: NList(d["PP"].get_children()))),
                    RewriteRule(
                        (NList([PatternDot("PD"),
                                PatternPlus("PP")
                                ]), Constraint(lambda d: isZero(d["PD"]))),
                        Replacement(lambda d: NList(d["PP"].get_children())))
                ])
                lhss[i][j] = cell
        #

        # [CHECK] parts = self.partitionings
        #parts = self.basic_partitionings
        parts = self.partitionings
        eqs = map_thread(Equal, [lhss, parts[outops[0].get_name()]], 2)

        output_shape = self.basic_partitionings[outops[0].get_name()].shape
        r, c = output_shape
        for eq in self.solved_subequations:
            lhs, rhs = eq.get_children()
            for row in range(r):
                for col in range(c):
                    this_lhs, this_rhs = eqs[row][col].get_children()
                    if lhs == this_lhs:
                        eqs[row][col].set_children(1, rhs)

        #for row in range(r):
        #for col in range(c):
        #eqs[row][col] = equation2replacement( eqs[row][col].get_children()[1] )

        replacement_str = equation2replacement(
            BlockedExpression(eqs, (0, 0), output_shape))
        #", ".join([
        #"[ " + ", ".join( [ eq for eq in row ] ) + " ]"
        #for row in eqs ]) + " ]" + \
        #", (0,0), (%d, %d) )" % (r, c) + \
        #"]), " + \
        #"BlockedExpression([ " + \
        #", ".join([
        #"[ " + ", ".join( [ eq for eq in row ] ) + " ]"
        #for row in eqs ]) + " ]" + \
        #", (0,0), (%d, %d) )" % (r, c) + \
        #"])" # size does not matter
        print("* Learnt PME pattern")
        print("*     ", RewriteRule(pattern, Replacement(replacement_str)))
        self.known_pmes.append(
            RewriteRule(pattern, Replacement(replacement_str)))
        with open(os.path.join("OUTPUT", self.name + "_pmes"),
                  "ab+") as pmes_f:
            pickle.dump(self.known_pmes[-1], pmes_f)
Ejemplo n.º 15
0
    def fix_temporaries(self):
        temp_exprs = []
        for expr in itertools.chain(*self.expressions):
            lhs, rhs = expr.get_children()
            for out in lhs:
                if not out.isInput() and not out.isOutput(
                ):  # [FIXME] Temporaries are not labeled. Now they are, fix.
                    self.linv_operands.append(out)
                    temp_exprs.append(expr)
        for expr in temp_exprs:
            #print( expr )
            lhs, rhs = expr.get_children()
            lhs = lhs.get_children()[0]
            # Determine to which operands in the temporary bound
            # Also, which quadrant of the full temporary should be used
            (rows_op, r_dim), (cols_op,
                               c_dim) = utils.size_as_func_of_operands(rhs)

            # set in bound_dimensions
            r = rows_op.parent_op.get_name() + "_" + r_dim.lower()
            for s in self.linv_bound_dimensions:
                if r in s:
                    s.append(lhs.get_name() + "_r")
            c = cols_op.parent_op.get_name() + "_" + c_dim.lower()
            for s in self.linv_bound_dimensions:
                if c in s:
                    s.append(lhs.get_name() + "_c")

            # partition temporary
            rows_parent = rows_op.parent_op.get_name()
            cols_parent = cols_op.parent_op.get_name()
            shape_rows = self.pme.part_shape[rows_parent][{
                "R": 0,
                "C": 1
            }[r_dim]]
            shape_cols = self.pme.part_shape[cols_parent][{
                "R": 0,
                "C": 1
            }[c_dim]]

            size_rows = rows_op.parent_op.get_size()[{"R": 0, "C": 1}[r_dim]]
            size_cols = cols_op.parent_op.get_size()[{"R": 0, "C": 1}[c_dim]]
            lhs.size = (size_rows, size_cols)

            part = partition_shape(lhs, (shape_rows, shape_cols))
            self.linv_operands_basic_part[lhs.get_name()] = part
            part_shape = (len(part.children), len(part.children[0]))
            self.linv_operands_part_shape[lhs.get_name()] = part_shape

            part_rows = rows_op.quadrant[{"R": 0, "C": 1}[r_dim]]
            part_cols = cols_op.quadrant[{"R": 0, "C": 1}[c_dim]]
            quadrant = part[part_rows][part_cols]

            # replace the temporary with the proper quadrant in every expression of the linv
            # [TODO] why is loop invariant a list of lists?
            expressions = []
            for expr_l in self.expressions:
                expressions.append([
                    replace(copy.deepcopy(expr),
                            [RewriteRule(lhs, Replacement(quadrant))])
                    for expr in expr_l
                ])
            self.expressions = expressions
Ejemplo n.º 16
0
    def is_feasible(self):
        pme = self.pme
        linv = self.expressions

        traversal_tuples = [[0] if shape == 1 else [1, -1]
                            for shape in pme.part_tuple]
        feasible_traversals = []
        # For peeling in slingen mode
        #self.iteration_rules = []

        for traversal_dirs in itertools.product(*traversal_tuples):
            dims_to_part_shape = {}
            #for dims, shape in zip( self.operation.bound_dimensions, traversal_dirs ):
            for dims, shape in zip(self.linv_bound_dimensions, traversal_dirs):
                for dim in dims:
                    dims_to_part_shape[dim] = shape
            initial_rules = []
            final_rules = []
            trav_shape = dict()
            #for operand in self.operation.operands:
            for operand in self.linv_operands:
                trav_shape[operand.get_name()] = (
                    dims_to_part_shape[operand.get_name() + "_r"],
                    dims_to_part_shape[operand.get_name() + "_c"])
                initial_rules.extend(
                    #initial_rewrite(operand, pme.basic_partitionings[operand.get_name()], trav_shape[operand.get_name()])
                    initial_rewrite(
                        operand,
                        self.linv_operands_basic_part[operand.get_name()],
                        trav_shape[operand.get_name()]))
                final_rules.extend(
                    #final_rewrite(operand, pme.basic_partitionings[operand.get_name()], trav_shape[operand.get_name()])
                    final_rewrite(
                        operand,
                        self.linv_operands_basic_part[operand.get_name()],
                        trav_shape[operand.get_name()]))
            pre = []
            post = []

            for expr in itertools.chain(*linv):
                new = copy.deepcopy(expr)
                pre.append(simplify(to_canonical(replace(new, initial_rules))))
                new = copy.deepcopy(expr)
                post.append(simplify(to_canonical(replace(new, final_rules))))
            # check if basic init
            basic_init = True
            for expr in pre:
                lhs, rhs = expr.get_children()
                if not all( op.isZero() for op in lhs ) and not \
                        isOperand( rhs ):
                    basic_init = False
                    break
            if not basic_init:
                continue
            # check if linv and not guard -> post
            #final_status = [ replace( copy.deepcopy(expr), self.op_to_implicit ) for expr in post ]
            final_status = post
            #rules1 = []
            #rules2 = []
            #neweq = replace( copy.deepcopy(self.operation.equation), [self.pme.known_ops[-1]] )
            neweq = replace(copy.deepcopy(self.operation.equation),
                            self.pme.known_ops)
            # [FIXME] Generalize
            implies_post = True
            if not neweq in final_status:
                implies_post = False
                continue
            feasible_traversals.append((trav_shape, pre, post))
            # Store these states for use in loop peeling (LGenCode)
            #self.iteration_rules.append( (initial_rules, final_rules) )

        if len(feasible_traversals) > 1:
            print("* More than one traversal for this LoopInvariant: %d" %
                  len(feasible_traversals))
        self.traversals = feasible_traversals
        return bool(feasible_traversals)