генерация оптимизированного октавного кода от sympy - PullRequest
0 голосов
/ 07 января 2019

У меня есть несколько огромных матриц для экспорта, которые содержат только sin (q), cos (q) и суммы / множители из них. Sympy может рассчитать и экспортировать это в октаву - что удивительно! Однако, поскольку это большие матрицы, мне нужна какая-то cse или даже лучшая специализированная оптимизация.

Я нашел этот замечательный учебник для кода C с помощью cse . Поэтому я попытался перенести его, но у меня не получилось уточнить некоторые детали в классе принтеров. Я думаю, что это бесконечная рекурсия, приводящая к RecursionError: maximum recursion depth exceeded.

Мой вопрос: есть ли пример того, как сочетаются октавный кодоген и оптимизация? Или может кто-нибудь помочь мне запустить приложенную mwe?

import sympy as sp
t = sp.symbols('t')

from sympy.printing.octave import OctaveCodePrinter
from sympy.printing.octave import Assignment
class matlabMatrixPrinter(OctaveCodePrinter):

    def _print_ImmutableDenseMatrix(self, expr):
        sub_exprs, simplified = sp.cse(expr)
        lines = []
        for var, sub_expr in sub_exprs:
            lines.append( self._print(Assignment(var, sub_expr)))
        M = sp.MatrixSymbol('M', *expr.shape)
        return '\n'.join(lines) + '\n' + self._print(Assignment(M, expr))

tmp = sp.sin(t)+sp.sin(t)**2
tmp = sp.ImmutableDenseMatrix((1,1,tmp))
se, ex = sp.cse(tmp)
print((ex,se))
print('\n')
#tmp = sp.Matrix([2*sp.sin(t),sp.sin(t)])
p = matlabMatrixPrinter()
print(p.doprint(tmp))

Edit: теперь я понял, что второе присваивание в операторе return также выполняет функцию _print_ImmutableDenseMatrix, так что это в конечном итоге является рекурсией. Я не знаю, почему в учебнике это не проблема для C-кода, но здесь он работает рекурсивно. Кажется, это проблема только самого упрощенного выражения, которое не может вызвать функцию self._print. Может быть, кто-то что-то знает об этих принтерах и о том, как печатать матрицы и это единственное задание?

1 Ответ

0 голосов
/ 20 января 2019

После многих экспериментов я чувствую, что все еще понимаю лишь некоторые намерения, стоящие за преднамеренным рабочим процессом codePrinter. Тем не менее, я написал подкласс, который работает точно так, как я планировал (осторожно, поскольку это, вероятно, не работает ни с чем, кроме матриц)!

Может быть, это кому-то пригодится! Для меня это определенно подтверждает, что sympy является рабочим инструментом, поскольку в противном случае тысячи sin оценок были бы абсолютно нежизнеспособным кодом.

Меня все равно очень интересуют комментарии и мысли кого-то, кто может знать, как ДОЛЖНЫ быть реализованы эти функции!

import sympy as sp
t = sp.symbols('t')
from sympy.printing.octave import OctaveCodePrinter
from sympy.printing.octave import Assignment
class matlabMatrixPrinter(OctaveCodePrinter):
    def print2(self,expr_list,names=None):
        sub_exprs, simplified = sp.cse(expr_list)
        lines = []
        for var, sub_expr in sub_exprs:
            lines.append(self._print(Assignment(var, sub_expr)))
        lines.append('')
        for k,expr in enumerate(simplified):
            if names:
                M = sp.MatrixSymbol(names[k],*expr.shape)
            else:
                M = sp.MatrixSymbol('M{k}'.format(k=k), *expr.shape)
            lines.append(self._print(Assignment(M,expr)))
        result = ''
        return '\n'.join(lines)

tmp = sp.Matrix([sp.sin(t)+sp.sin(t)**2 ])
tmp2 = sp.Matrix([sp.sin(t),sp.cos(t),2*sp.sin(t),sp.cos(t)**2])

p = matlabMatrixPrinter()
#print(p.print2([tmp,tmp2]))
print(p.print2([tmp,tmp2],['scalar_matrix','matrix']));

И это дает ожидаемый результат:

x0 = sin(t);
x1 = cos(t);
scalar_matrix = x0.^2 + x0;
matrix = [x0; x1; 2*x0; x1.^2];

Как описано выше: используйте на свой страх и риск:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...