Как построить подвыражения только с двумя переменными и одной арифметической операцией из сложного выражения Maple / Matlab? - PullRequest
0 голосов
/ 18 сентября 2018

позвольте символическому выражению, как показано ниже.

y = s + (a/b)*log((a+c)/(b*a)); %# it can be any type of expression

как я могу получить все возможные подвыражения с двумя переменными и одним оператором между ними.

subExpression1 = b*a;
subExpression2 = a/b;

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

Есть ли способ изучить как LHS, так и RHS оператора ??

любые комментарии и предложения будут очень полезны

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Вы можете попробовать полудокументированную утилиту mtree, чтобы создать дерево разбора , которое можно использовать для анализа допустимых строк кода (включая символику), а также целых файлов.Вот как его использовать:

tree = mtree('y = s + (a/b)*log((a+c)/(b*a));');

С ним можно делать все что угодно, например, выводить его в текст:

>> tree.dumptree

  1  *<root>:  EXPR:   1/03 
  2     *Arg:  EQUALS:   1/03 
  3        *Left:  ID:   1/01  (y)
  4        *Right:  PLUS:   1/07 
  5           *Left:  CALL:   1/05 
  6              *Left:  ID:   1/05  (s)
  7           *Right:  MUL:   1/14 
  8              *Left:  PARENS:   1/09 
  9                 *Arg:  DIV:   1/11 
 10                    *Left:  CALL:   1/10 
 11                       *Left:  ID:   1/10  (a)
 12                    *Right:  CALL:   1/12 
 13                       *Left:  ID:   1/12  (b)
 14              *Right:  CALL:   1/18 
 15                 *Left:  ID:   1/15  (log)
 16                 *Right:  DIV:   1/24 
 17                    *Left:  PARENS:   1/19 
 18                       *Arg:  PLUS:   1/21 
 19                          *Left:  CALL:   1/20 
 20                             *Left:  ID:   1/20  (a)
 21                          *Right:  CALL:   1/22 
 22                             *Left:  ID:   1/22  (c)
 23                    *Right:  PARENS:   1/25 
 24                       *Arg:  MUL:   1/27 
 25                          *Left:  CALL:   1/26 
 26                             *Left:  ID:   1/26  (b)
 27                          *Right:  CALL:   1/28 
 28                             *Left:  ID:   1/28  (a)

Обратите внимание, что при выполнении бинарных операций (например,PLUS или MUL) за ними следуют строки *Left и *Right, содержащие операнды.

Загляните внутрь MATLAB\R20###\toolbox\matlab\codetools\@mtree\mtree.m для получения дополнительной информации о том, что можно сделать с помощью этихобъекты.

0 голосов
/ 18 сентября 2018

Во-первых, в вашем выражении нет подвыражения a*b. Внутри звонка на log в вашем непарсированном входе появляется подтерма c/b*a. Но в синтаксисе Maple он разбирается на что-то математически эквивалентное (c*a)/b, а не c/(b*a).

Но ваш вопрос содержит другую двусмысленность. Давайте рассмотрим несколько примеров:

restart;

expr1 := y = s + (a/b)*log(a+c/b*a);

                                  c a
                         a ln(a + ---)
                                   b
        expr1 := y = s + -------------
                               b

expr2 := y = s + a*log(a+c/b*a)/b;

                                  c a
                         a ln(a + ---)
                                   b
        expr2 := y = s + -------------
                               b

expr2 - expr1;

                    0 = 0

Таким образом, expr1 и expr2 математически эквивалентны. Клен даже держит их структуры одинаково, внутри. (Вы можете проверить это с помощью команд lprint и dismantle.)

Таким образом, вы, похоже, просите, чтобы a/b был распознан в любом из них, после синтаксического анализа ввода , даже если этот термин не появляется в виде буквально во входных данных (до синтаксического анализа). По сути, это не так, но нам нужно знать, что это часть ваших ожиданий. Если a/b должен быть распознан как возможное поджатие этого значения, независимо от того, введено ли оно как expr1 или expr2, то это ключевая деталь. Если это не ваше желание, то вам действительно придется обосновать, как их можно отличить друг от друга после анализа (поскольку они могут анализировать одно и то же , в зависимости от того, что уже произошло в сеансе Клен!).

Кроме того, как вы собираетесь обрабатывать что-то, что математически эквивалентно (a*s)/(b)? Вы хотите код, который возвращает все возможные арифметические пары, например. a*s, a/b, s/b? Или вы хотите просто a*s, или просто a/b, или просто s/b?

Теперь рассмотрим другой пример:

expr3 := a+c*a/b;

                            c a
               expr3 := a + ---
                             b

normal(expr3);

                   a (b + c)
                   ---------
                       b

Они математически эквивалентны, хотя хранятся по-разному. В зависимости от вашего определения приемлемого «подвыражения» вы можете или не хотите хотеть a/b, или c/b, или b+c, в ваших результатах.

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

...