예제 #1
0
def generate_operand(rows, columns):
    global _n
    _n += 1
    if columns == rows:
        if rows == 1:
            return # scalar

        operand = ae.Matrix('M{}'.format(_n), size=(rows, columns))
        operand.set_property(properties.FULL_RANK)
        # include "no property"
        if random.random() > 0.25:
            operand.set_property(random.choices([properties.DIAGONAL, properties.LOWER_TRIANGULAR, properties.UPPER_TRIANGULAR, properties.SYMMETRIC, properties.SPD])[0])
        return operand
    elif columns == 1:
        return ae.Vector('v{}'.format(_n), size=(rows, columns))
    elif rows == 1:
        return ae.Vector('v{}'.format(_n), size=(rows, columns))
    else:
        operand = ae.Matrix('M{}'.format(_n), size=(rows, columns))
        operand.set_property(properties.FULL_RANK)
        return operand
예제 #2
0
def generate_matrix(rows, columns):
    global _counter
    _counter += 1
    operand = ae.Matrix("M{}".format(_counter), (rows, columns))
    operand.set_property(properties.FULL_RANK)
    if rows == columns and random.random() > 0.25:
        operand.set_property(
            random.choice([
                properties.DIAGONAL, properties.LOWER_TRIANGULAR,
                properties.UPPER_TRIANGULAR, properties.SYMMETRIC,
                properties.SPD
            ]))
    return operand
예제 #3
0
def randomize_sizes(expr, rows=None, cols=None):
    can_change = False
    if rows is None:
        rows = random_dimension()
    if cols is None:
        can_change = True
        cols = random_dimension()
    if isinstance(expr, ae.Symbol):
        if rows == 1 or cols == 1:
            if rows == cols:
                return ae.Scalar(expr.name.replace('M', 'a'))
            else:
                return ae.Vector(expr.name.replace('M', 'v'), (rows, cols))
        return ae.Matrix(expr.name, (rows, cols))
    try:
        if isinstance(expr, ae.Times):
            operands = []
            new_rows = rows
            for operand in expr.operands[:-1]:
                new_cols = random_dimension()
                try:
                    operands.append(
                        randomize_sizes(operand, new_rows, new_cols))
                    new_rows = new_cols
                except NeedQuadratic:
                    operands.append(
                        randomize_sizes(operand, new_rows, new_rows))
            try:
                operands.append(
                    randomize_sizes(expr.operands[-1], new_rows, cols))
            except NeedQuadratic:
                operands.append(
                    randomize_sizes(expr.operands[-1], new_rows, new_rows))
            return ae.Times(*operands)
        if isinstance(expr, ae.Transpose):
            return ae.Transpose(randomize_sizes(expr.operand, cols, rows))
        if isinstance(expr, (ae.Inverse, ae.InverseTranspose)):
            if rows != cols:  # Inversion needs a quadratic matrix or a scalar
                raise NeedQuadratic()
            return type(expr)(randomize_sizes(expr.operand, rows, rows))
        if isinstance(expr, ae.Operator):
            return type(expr)(*(randomize_sizes(operand, rows, cols)
                                for operand in expr.operands))
        assert False, "Unreachable"
    except NeedQuadratic:
        if not can_change:
            raise
        return randomize_sizes(expr, rows, rows)
예제 #4
0
def generate_equation(n_ops):
    expr_size = operand_sizes()
    out = ae.Matrix("out", expr_size)
    expr = simplify(generate_expression(n_ops, expr_size))
    return aeq.Equations(ae.Equal(out, expr))
예제 #5
0
def matrix_chain_generator():
    while True:
        # for _ in range(20):
        #     expression_strategy.example()
        # generate_matrix_chain()

        length = random.randrange(4, 10)
        sizes = []

        if  0.95 <= random.random():
            sizes.append(1)
        else:
            sizes.append(matrix_size())

        for i in range(length):
            rand = random.random()
            if  0.6 <= rand < 0.95:
                # square
                sizes.append(sizes[i])
            elif 0.95 <= rand:
                # vector
                sizes.append(1)
            else:
                # non-square
                sizes.append(matrix_size())

        # print(sizes)
        operands = []
        restart = False
        for rows, columns in window(sizes):
            if rows == columns:
                if rows == 1:
                    restart = True
                    break
                    # operands.append(None) # error
                op = random.choices([ae.Identity, ae.Transpose, ae.Inverse, ae.InverseTranspose], weights=[2, 1, 1, 1])[0]
                operands.append(op(generate_operand(rows, columns)))
            elif rows == 1:
                operands.append(ae.Transpose(generate_operand(columns, rows)))
            elif columns == 1:
                operands.append(generate_operand(rows, columns))
            else:
                op = random.choices([ae.Identity, ae.Transpose], weights=[3, 1])[0]
                if op == ae.Transpose:
                    operands.append(op(generate_operand(columns, rows)))
                else:
                    operands.append(op(generate_operand(rows, columns)))
        if restart:
            continue

        # print(operands)
        expr = ae.Times(*operands)
        expr = simplify(expr)
        # print(expr)

        # print(expr.size)
        # print((sizes[0], sizes[-1]))
        if expr.has_property(properties.MATRIX):
            lhs = ae.Matrix('X'.format(_n), size=(sizes[0], sizes[-1]))
        elif expr.has_property(properties.VECTOR):
            lhs = ae.Vector('x'.format(_n), size=(sizes[0], sizes[-1]))

        yield Equations(ae.Equal(lhs, expr))
예제 #6
0
def next_matrix():
    global _n
    _n += 1
    return ae.Matrix('M{}'.format(_n), size=(5, 5))