Ускорение динамического составления символьных переменных - PullRequest
0 голосов
/ 10 июня 2019

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

Я пытаюсь разработать интерфейс для построения дерева выражений, которое будет выводить уравнение, котороеподается в мой синтезатор.

Синтезатор генерирует таблицу из 256 значений, которые интерполируются в зависимости от того, как переменные используются в уравнении.Например, «w» относится к оси X одного сигнала.'y' оценивает текущую позицию в таблице, разделенную на 256. Таким образом, вы можете сгенерировать простую форму морфинга, например:

(1-y)*sin(w)+y*cos(w)

(https://i.imgur.com/2xh2Nc2.png)

Вот функция, которая обновляет график при смене ползунка.

this.plotLine = fplot(this.wavePlot, sym('x'));
function plotRefresh(src, event)
            yVal = (event.Value-1)/255;
            set(this.yLabel, 'Value', string(yVal));
            set(this.zLabel, 'Value', string(yVal*2-1));
            set(this.plotLine, 'Function', subs(this.eTree.activeSym, sym('y'), yVal));
        end

Каждый узел в дереве имеет символическое выражение следующим образом. Когда новый узел добавляется в дерево, его дочерние элементы передаются ванонимная функция для генерации выражения в этой точке дерева.

                case nTypes.W
                    sy = sym('w');
                case nTypes.X
                    sy = sym('w')*2-1;
                case nTypes.Y
                    sy = sym('y');
                case nTypes.Z
                    sy = sym('y')*2-1;
                case nTypes.ADD
                    sy = @(n)fold(@(a,b)a+b, n);
                case nTypes.SUBTRACT
                    sy = @(n)fold(@(a,b)a-b, n);
                case nTypes.MULTIPLY
                    sy = @(n)fold(@(a,b)a*b, n);
                case nTypes.DIVIDE
                    sy = @(n)fold(@(a,b)a/b, n);
                case nTypes.EXPONENTIATE
                    sy = @(n)fold(@(a,b)a^b, n);
                case nTypes.AND
                    sy = @(n)fold(@(a,b)and(a, b), n);
                case nTypes.OR
                    sy = @(n)fold(@(a,b)or(a, b), n);
                case nTypes.EQUAL
                    sy = @(n)fold(@(a,b)eq(a, b), n);
                case nTypes.NOTEQUAL
                    sy = @(n)fold(@(a,b)ne(a, b), n);
                case nTypes.GREATER
                    sy = @(n)fold(@(a,b)gt(a, b), n);
                case nTypes.LESSER
                    sy = @(n)fold(@(a,b)lt(a, b), n);
                case nTypes.GREATEROREQ
                    sy = @(n)fold(@(a,b)ge(a, b), n);
                case nTypes.LESSEROREQ
                    sy = @(n)fold(@(a,b)le(a, b), n);
                case nTypes.MIN
                    sy = @(n)fold(@(a,b)piecewise(a<=b, a, a>b, b), n);
                case nTypes.MAX
                    sy = @(n)fold(@(a,b)piecewise(a>=b, a, a<b, b), n);
                case nTypes.SIN
                    sy = @(n)sin(n{:});
                case nTypes.COS
                    sy = @(n)cos(n{:});
                case nTypes.TAN
                    sy = @(n)tan(n{:});

Я попытался реализовать это без символьных выражений, и это работает намного быстрее. В этом случае каждый узел имел двойной / встроенный дескриптор,который взял бы своих потомков в качестве параметра для первой анонимной функции, а затем возвратил бы другую анонимную функцию, которая выполняла бы ее оценку, учитывая глобальные переменные w и y.

                case nTypes.SIN
                    sy = @(children)@(w, y)sin(children(w, y));

Затем я сделал массив ячеек 512x256 для кэшированиязначения для каждой возможной позиции ползунка.

   cached = cellfun(@(y)cellfun(@(w)tNode.sy(w, y), linspace(0, 1, 512)), linspace(0, 1, 256))

Затем, когда ползунок изменяется, я делаю set(gca, 'YData', cached{sliderPosition}) Имея значения cached сделал обновление сюжета намного более плавным.Однако, если есть способ кеширования аналогичным образом с использованием символьной оценки вместо дерева глубоко вложенных анонимных функций, это предпочтительнее.

Возможно ли это?

...