Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2docx-1.doc
Скачиваний:
3
Добавлен:
01.03.2025
Размер:
2.27 Mб
Скачать

33. Подходы к символьному упрощению выражений.

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

rule(A*B, B*A). // rule(A+B, B+A). // rule(A+B+C, А+(В+С)).

rule(А*В*С, А*(В*С)). // rule(А*В/С, А*(B/С)) .

rule(A*(E+C), А*В+А*С). // rule(A*(B-C), А*В-А*С).

rule(A*B+A*C, A*(B+С)). // rule(А*В -А*С, А*(В-С)).

rule((А+В)*(А-В), А*А-В*В). // rule(А*А-В*В, (А-В)*(А-В)).

rule(A*X+X, (А+1)*Х). // rule (X, X).

Последнее правило возвращает исх.выр-е, рас­сматривая случай, когда выр-е упроще-нию не подлежит. Не все пра­вила ведут в сторону упрощения. Рассмотрим правила, которые вычисляют фрагменты выражения, содержащие числа:

compute(X+Y,Z):- integer(X), integer(Y) , Z is X+Y.

compute(X*Y,Z) :- integer(X), integer(Y), Z is X*Y.

compute(X-Y.Z) :- integer(X), integer(Y), Z is X-Y.

compute(1*X,X). // compute(0*X,0). // compute (0+X,0). // compute(X/X,1).

Пусть мы хотим упростить выр-е 1+2+х*3 Для упрощения следует попытать-ся применить процедуры упрощения к каж­д. из подвыр-й, содержащихся в дереве выр-я:

expr(Expr,Res) :-

Expr =.. [Op,А,В], expr(A.Al), expr(B.Bl), R =.. [Op.Al.Bl],

(compute(R,Res);rule(R,Res)).

expr(X,X) :- atomic(X).

Эта процедура упрощения не приводит к са­мому простому результату. Для симв-го сравнения выр-й необх.попытаться при­вести одно выр-е к др. при помощи эквив-х преобр-й. Предикат expr позволяет применить к выр-ю только один шаг пр-ия, но для приведения одного выражения к другому может потребоваться большее число шагов. Опред-м предикат convert который определяет при­водимость 2х выр-й друг к другу. Используем метод поиска в глубину с запоминанием уже рассмотренных выражений:

convert(X,R) :- search([X],CRIJ).

search(R,R).

search(P.R) :- prolong(P,Pl), search(Pl,R,D1).

prolong([XIT],[Y,XIT]) :- move(X.Y), not(member(Y,[X|T]))

(+)при совпа­дении выражений устанавливает идентичность достаточно быстро; (-)для несовпадающих выр-й дерево поиска может оказаться очень большим, с учетом мн-ва применимых правил преобразования. Можно ввести огр-е на глу­бину проводимого поиска,привязав эту длину к числу операций и/или операндов в выр-и. Альтернативно можно ис­пользовать поиск в ширину или с итерационным заглублением. Упрощение выражений. Предикат convert позволяет найти все возможные преобразования заданного выражения как более простые, так и более сложные. Имеет смысл поста-вить задачу нахождения наиболее простого выр-я, эквив-го данному, в смысле некот. критерия. Критерием простоты выр-я можно считать минимальное кол-во в нем знаков операций, либо мин.кол-во операндов, либо некот.комбинацию этих величин. Для опр-я веса вы­р-я (величины, противоположной простоте), введем предикат cost:

cost(X,0) :- number(X). // cost(X,I) :- atom(X).

cost(X,Z) :- X = .. [Op, A, B], cost(A,CA), cost(B,CB), Z is CA+CB+2.

Для упрощения выр-я исп-ем метод градиентного спус­ка, введем предикат search/4 со след.аргументами: 1.Текущий список выр-й для рассмотрения, все выр-я предполага-ются одинаковой стоимости С; 2.Стоимость С выр-й в списке; 3.Результирующее упрошенное выр-е; 4.Список выр-й длины С кот. уже были рассм. Процесс поиска инициируется при вызове основного предиката simplify/2 и начинается со списка из одного исходного выражения

simplify(E,R) :- cost(Е,С), search([Е],C,R,[]).

Далее мы каждый раз будем рассматривать 1е выр-е из списка, и пытаться упростить его всеми возможными способами при помощи предиката move_grad, кот. вызывает ехрг и возвращает только выр-я с тем же или меньшим весом.