7,8 лаба зі Ш.І / L8_Дифференцирование
.docЛабораторная работа № 8
Дифференцирование аналитических выражений
Представление выражений
Выражение состоит из констант, переменных, знаков операций. Для упрощения будем представлять выражение в виде вложенных функторов:
domains
expr = int(integer); представление числовых констант
var(symbol); представление переменных
sum(expr, expr); сумма выражений
sub(expr, expr); разность выражений
mult(expr, expr); произведение выражений
div(expr, expr); деление выражений
ln(expr); логарифм
sin(expr); синус
cos(expr) косинус
Запишем правила дифференцирования выражений. Этот блок правил простой и является представлением правил дифференцирования на языке Пролог.
Первая группа правил:
dif_expr(int(_),_,int(0)).
dif_expr(var(A),B,int(0)):-A<>B.
dif_expr(var(X),X,int(1)).
Первое правило указывает, что производная от константы равна нулю. В случае, когда дифференцирование производится по переменной, которая не входит в выражение, производная тоже равна нулю (2 правило). Третье правило это запись на прологе факта .
Запишем основные правила дифференцирования:
Производная суммы
dif_expr(sum(U,V),X,R):- dif_expr(U,X,U1), dif_expr(V,X,V1)
R:=sum(U1,V1).
Производная разности аналогична (записать самостоятельно)
Производная произведения
dif_expr(mult(U,V),X,R):- dif_expr(U,X,U1), dif_expr(V,X,V1)
R:=sum(mult(U1,V), mult(U,V1)).
Производная частного
dif_expr(div(U,V),X,R):- dif_expr(U,X,U1), dif_expr(U,X,U1)
R=div(sub(mult(U1,V), mult(U,V1)),mult(V,V)).
Производная логарифму
dif_expr(ln(U),X,R):- dif_expr(U,X,U1), R=div(U1,V).
Производная степени
Производные тригонометрических функций
dif_expr(sin(U), X, cos(U)).
dif_expr(cos(U), X, mult(int(-1),sin(U)).
Правило дифференцирования сложных функций
dif_expr(funct(U(X))
После дифференцирование выражение имеет некрасивый вид – содержит нули. Единицы, которые при ручном дифференцировании обычно автоматически опускаются. Например, выражение
X*0+ln(0+x) – ln(x+0)*1 фактически равно нулю
Для этой цели введем предикат reduce(expr,expr), в котором первый аргумент это выражение до упрощения а второй – после упрощения.
В нижеследующем правиле осуществляется упрощение суммы.
reduce(sum(X,Y),R);-reduce((X,X1), reduce((Y,Y1), sum_r(X1,Y1,R)
Первые две цели необходимы для упрощения слагаемых, а предикат sum_r(expr, expr) предназначен для упрощения суммы и является набором очевидных фактов и правил для этой операции.
sum_r(int(0), E, E).
sum_r(E, int(0), E).
ноль слева или справа в слагаемом можно опустить
sum_r(int(K), int(M) int(R)):-R=K+M.
Константы в сумме складываются.
sum_r(X, Y, sum(X,Y)). Предикат - ловушка
Упрощение разности
reduce(sub(X,Y),R);-reduce((X,X1), reduce((Y,Y1), sub_r(X1,Y1,R)
sub_r (E, E, int(0)). Разность одинаковых выражений
ноль слева и справа
sub_r(int(K), int(M) int(R)):-R=K–M. как учесть знак –
sub_r(X, Y, sub(X,Y)). Предикат - ловушка
Упрощение произведения
mult_r (int(0), _, int(0)). Умножение на ноль слева
mult_reduce (_, int(0), int(0)). Умножение на ноль справа
mult_reduce (int(1), E, E). Умножение на 1 слева
mult_reduce (E, int(1), E )). Умножение на 1 справа
mult_r(int(K), int(M) int(R)):-R=K*M.
mult_r(X, Y, mult(X,Y)). Предикат - ловушка
Упрощение частного
Поскольку упрощение не всегда возможно, последним предикатом в каждой группе должен быть предикат – ловушка.
Продифференцированное и упрощенное выражение представлено в префиксной форме записи. Естественнее выводить выражения в инфиксном виде. Введем предикат вывода выражения write_expr(expr).
Если аргумент – целое число или переменная, выводится значение константы или имя переменной.
write_expr(int(X) :-X>=0, write(X).
write_expr(var(X) :- write(X).
Если в выражение входят операции с разными приоритетами, возникает необходимость правило, которое расставляет скобки в необходимых случаях.
Составим предикат write_par(expr ), который действует следующим образом
write_par(E):-write(“(“),write_expr(E), write(“)“).
Вывод функции логарифм
write_expr(ln(X) :- write(“ln”),.write_par(X).
Правило вывода суммы, разности произведения, частного и возведения в степень различаются только знаком вывода знака
write_expr(sum(X,Y)):- write_expr(X), write(“+”), write_expr(Y).
write_expr(sub(X,Y)):- write_expr(X), write(“–”), write_expr(Y).
write_expr(mult(X,Y)):- write_expr(X), write(“*”), write_expr(Y).
write_expr(div(X,Y)):- write_expr(X), write(“/”), write_expr(Y).
write_expr(st(X,Y)):- write_expr(X), write(“^”), write_expr(Y).
Составим предикат специальной печати, имеющий следующую структуру
write_old(yun(X,Y)):-write_par(yun(X.Y)) *
write_old(yun(E):-write_yun(E)
здесь old- операция, приоритет, которой на единицу больше чем операции yun.
Первое из этих правил непосредственно расставляет скобки, второе обеспечивает поиск в базе знаний до тех пор, пока не встретиться ситуация, которая отвечает общим правилам вывода либо правилу (*). Для этого введем предикаты write_plus(expr), write_minus(expr) и т.д. Тогда эта предикатная группа имеет вид
write_minus(plus(X,Y)):-write_par(plus(X,Y)).
write_minus(E):-write_expr(E).
write_mult(minus(X,Y)):-write_par(minus(X,Y)).
write_minus(E):-write_expr(E);
write_div(mult(X,Y)):-write_ par (mult(E)).
write_div(E):-write_mult(E);
write_div(mult(X,Y)):-write_ par(mult(E)).
write_div(E):-write_mult(E);
Тогда группа правил для печати операций имеет вид
write_expr(minus(X,Y)):- write_expr(X), write(“–”), write_minus(Y).
write_expr(mult(X,Y)):- write_minus(X), write(“*”), write_minus(Y).
write_expr(div(X,Y)):- write_mult(X), write(“/”), write_div(Y).
write_expr(potens(X,Y)):- write_div(X), write(“^”), write_potens(Y).
Наибольшая вероятность возникновения ошибки в этой задаче может быть при формировании выражения из списка, поэтому целесообразно после того, как выражение получено проверить работу предиката s_expr в целом. Очевидно, что при нормальном завершении его работы исходный список должен быть пустым. В противном случае допущена ошибка и для ее анализа хорошо было бы иметь значение полученного выражения. Предикатная группа правил проверки check(list, expr) имеет следующий вид
check([],_):-!.
check(_,S):-write(S),write(“Error”).
Тогда цель будет иметь следующий вид
write(“Enter funcnion”), write(”f=”), readln(S), convert(S, Li),
s_expr(Li,Lo,E), check(Lo,E),
dif_expr(E,E_dif), reduce(E_dif, E_r), write”\n df/dx=”),
write_expr ( E_r).