Скачиваний:
38
Добавлен:
01.05.2014
Размер:
711.17 Кб
Скачать

22.2.Факторизация

Факторизация-первый метод, применяемый решателем при решении уравнения. Отметим, что проверка применимости факторизации выполняется очень просто, она заключается в унификации с уравнением A*B=0.Если проверка успешна, то простейшие уравнения решаются рекурсивно. Предложение верхнего уровня, реализующее факторизацию, имеет вид

solve_equation(А*В=0, X, Solution)

factorize (A*В, X, Factors\[ ]),

remove_duplicates (Factors, Factors1),

solve_factors(Factors1, X, Solution).

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

22.3. Метод изоляции

Для указания места единственного вхождения неизвестного и его обработки полезно ввести понятие позицииподтерма в терме. Позиция подтерма в терме - это список номеров аргумента, описывающий местоположение подтерма. Рассмотрим уравнение cos(x)=0.Терм cos(x),содержащийх,является аргументом уравнения, ах-первый (и единственный) аргумент cos(x).Следовательно, позицияхвcos(x) =0определяется списком [1,1].Список [1,2,2,1]определяет позициюхв терме 1-2sin(х)=0.Соответствующие диаграммы представлены на рис. 22.2. Предложение, определяющее метод изоляции, имеет вид

solve_equation(Equation, X, Solution) 

single_occurrence (X, Equation),

position (X, Equation, [Side | Position]),

maneuver_sides (Side, Equation, Equation1),

isolate (Position, Equation1, Solution).

Условие, характеризующее применимость метода изоляции, состоит в проверке единственного вхождения переменной Хв уравнение. Такая проверка осуществляется с помощью предиката single_occurrence.ПозицияХвычисляется с помощью предиката position.Затем изоляцияХпроводится в два этапа. Сначала предикат

Рис. 22.2 Позиция подтермов в термах

maneuver_riflesобеспечивает вхождениеХв левую часть уравнения, а потом с помощью предиката isolate Xстановится субъектом формулы.

Помимо предиката single_occurrenceполезно определить более общий предикатoccurrence(Subterm, Term, N),который подсчитывает число Nвхождений подтермаSubtermв терм Term.Как предикат occurепсе,так и предикат positionпредставляют собой типичные предикаты структурных проверок. Оба предиката предлагалось запрограммировать в качестве упражнений к разд. 9.2.Программные тексты этих предикатов содержатся в разделе «Утилиты» программы 22.1.

solve_equation(Equation, Unknown, Solution)

Solution это решение уравнения Ecuation с неизвестным Unknown.

solve_equation(A*B = 0,X, Solution) 

!,

factorize (A*B,X, Factors \[ ]),

remove_duplicates (Factors, Factors1),

solve_.factors(Factorsl, X, Solution).

solve_equation(Equation, X, Solution) 

single_occurrence (X, Equation),

!,

position(X, Equation, [Side | Position]),

maneuver_sides(Side, Equation, Equation!),

isolate(Position, Equation1,Solution).

solve_equation(Lhs = Rhs, X, Solution) 

polynomial(Lhs,X),

polynoinial(Rhs,X),

!,

polynomial_normal_form(Lhs-Rhs, X, PolyForm),

solve_polynomial_equation(PolyForm, X, Solution).

solve_equation (Equation, X, Solution)

homogenize(Equalion, X, Equation1, X1),

!,

solve_equation (Equation1 .X1, Solution1),

solve_equation (Solution1 ,X. Solution).

Метод факторизации

facforize(Expression, Subterm, Factors)

расщепление мультипликативного терма Expression вразностный список множителей Factors,содержащий подтерм Subterm.

factorize(A*В, X, Factor \ Rest) 

!, faciorize(A, X, Factors\Factorsl),

factorize(B, X, Factorsl\Rest).

factorize(C,X,[C | Factors] \ Factors) 

subterm(X,C),!.

factorize(C, X, Factors \ Factors).

solve_factors(Factors, Unknown,Solution)

Solution-это решение уравнения Factor = 0 неизвестным Unknown для некоторого множителя Factor в списке Factors.

solve_factors([Factor | Factors],X, Solution) 

solve_equation (Factor = 0, X, Solution).

solve_factors([Factor | F.ictors],X,Solution) 

solve_factors (Faclor, X, Solution).

Метод изоляции

single_occurrence(Subterm,Term) 

occurrence(Subterm,Term, 1).

maneuver_sides (l, Lhs = Rhs,Lhs = Rhs)  !,

maneuver_sides(2, Lhs = Rhs, Rhs = Lhs)  !.

isolate([N | Position], Equation, IsolatedEqualion) 

isolax(N, Equation, Equation 1),

isolate(Position, Equation1, IsolatedEquation).

isolate([ ], Equation, Equation).

Аксиомы, используемые в методе изоляции

isolax(1, -Lhs=Rhs, Lhs=-Rhs). %Унарный минус

isolax(l, Terml + Term2=Rhs, Term1=Rhs-Term2). %Сложение

isolax(2,Terml+Term2=Rhs, Term2=Rhs-Term1). %Сложение

isolax(l,Terml-Term2=Rhs, Term1 = Rhs + Term2), %Вычитание

isolax(2,Terml-Term2=Rhs, Term2=Term1-Rhs). %Вычитание

isolax(l,Terml*Term2=Rhs, Term1=Rhs/Term2)  %Умножение

Term2  0

isolax(2,Terml*Term2 = Rhs, Term2 = Rhs / Term1 ) %Умножение

Term1 0

isolax(1, Term1  Term2 = Rhs, Term2 = Rhs  (-Term2)). %Возведение в %степень

isolax(2,Term  Term2 = Rhs, Term2=log(base(Terml),Rhs)) %Возведение в%степень

isolax(l, sin (U) = V,U = arcsin (V)). %Синус

isolax(l, sin (U) = V, U = - arcsin (V)). %Синус

isolax(l, cos (U) = V,U = arccos (V)). %Косинус

isolax(l, cos (U) = V,U = -arccos (V)). %Косинус

Полиномиальные методы

polynomial(Term, X) См. программу 11,4.

polynomial_normal_form (Expression, Term, Poly NormalForm)

PolyNormalForm-это полиномиальная нормальная форма выражения Expression, которая является полиномом от Term.

polynomial_normal_form(Polynomial, X, NormalForm) 

polynomial_form(Polynomial, X, PolyForm),

remove_zero_terms(PolyForm, NormalForm),!.

polynomial_form(X, X, [(1,1)]).

polynomial_form(X  N, X, [(1,N)]).

polynomial_form(Terml+Term2, X, PolyForm) 

polynomial_form(Terml, X, PolyForml),

polynomial_form (Term2, X,PolyForm2),

add_polynomials(PolyForml, PolyForm2, PolyForm).

polynomial_form(Terml-Term2, X, PolyForm) 

polynomial_form(Term1, X, PolyForm1),

polynomial_form(Term2, X, PolyForm2),

subtract_polynomials(PolyForml, PolyForm2, PolyForm),

polynomial_form (Term1*Term2, X, PolyForm) 

polynomial_form (Term1, X, PolyForm1),

poiynomial_form (Term2, X, PolyForm2),

multiply _polynomials(PolyForml, PolyForm2, PolyForm).

polynomial_form(Term  N, X, PolyForm)  !,

polynomial_form(Term, X, PolyForm1),

binomial(PolyForm1, N, Poly Form).

polynomial_form (Term, X, [(Term, 0)]) 

free_of(X, Term),!.

remove_zero_terms([(0,N) | Poly], Poly1) 

!, remove_zero_terms(Poly, Poly1).

remove_zero_terms([(C,N) | Poly],[(C,N) | Poly1]) 

С  0,!, remove_zero_terms (Poly, Poly1).

remove_zero_terms([ ],[ ]).

Программы действий с полиномами

add_polynomials (Poly1, Poly2, Poly)

Poly-сумма полиномов Poly1и Poly2, где Poly1, Poly2и Polyявляются полиномиальными формами.

add_polynomials([ ], Poly, Poly)  !.

add_polynomials(Poly, [ ], Poly)  !.

add_polynomials([(Ai,Ni) | Polyl],[(Aj,Nj) | Poly2],[(Ai,Ni) | Poly]) 

Ni > Nj, !, add_polynomials(Polyl,[(Aj,Nj) Poly2],Poly).

add_polynomials([(Ai, Ni)| Polyl],[(Aj, Nj) | Poly2],[(A, Ni)) Poly]) 

Ni =:= Nj,!, A:=Ai + Aj, add_polynomials(Polyl, Poly2, Poly).

add_polynomials([(Ai, Ni) | Poly1],[(Aj,Nj) | Poly2],[(Aj, Nj) | Poly]) 

Ni < Nj,!,

add_polynomials ([(Ai, Ni) | Poly1], Poly2, Poly).

subtract_polinomials (Poly1, Poly2, Poly)

Poly-разность многочленов Polylи Poly2,где Polyl, Poly2и Polyявляются полиномиальными формами.

subtract_polynomials (Poly1, Poly2, Poly) 

multiply_single(Poly2, ( -1,0), Poly3),

add_polynomials(Poly1, Poly3, Poly),!.

multiply_single (Polyl, Monomial, Poly)

Poly- произведение полинома Polyl на одночлен Monomial, где Polyl и Poly являются полиномиальными формами, а одночлен Monomial представлен в форме (С,N), обозначающей одночлен C*X**N.

multiply_single([(C1, N1) | Poly1],(C,N),[(C2,N2)| Poly]) 

C2:=C1*C,N2:=N1 + N,multiply_single(Polyl,(C,N),Poly).

multiply_single([ ], Factor, [ ]).

multiply_polynomials (Poly1, Poly2. Poly) 

Poly-произведение многочленов Polylи Poly2; Polyl, Poly2и Polyявляются полиномиальными формами.

multiply_polynomials([(C,N) Poly1], Poly2, Poly)

multiply_single(Poly2,(C,N), Poly3),

multiply_polynomials(Poiyl, Poly2, Poly4),

add_polynomials(Poly3, Poly4, Poly).

multiply_polynomials([ ],P,[ ]).

binomial(Poly, l. Poly).

Решатель алгебраических уравнений

solve_polynomial_equation(Equation, Unknown, Solution)

Solution - решение алгебраического уравнения Equation с неизвестным Unknown.

solve_polynomial_equation(PolyEquation, X, X =-B/A) 

linear(PolyEquation),!,

pad(PolyEquation, [(A,l),(B,0)]).

solve_polynomial_equation (PolyEquation, X, Solution) 

quadratic(PolyEquation),!,

pad(PoIyEquation,[(A,2),(B,l),(C,0)]),

discriminant(A,B,C, Discriminant),

root(X, A, B, Discriminant, Solution).

discriminant(A,B.C,D)  D:=B*B-4*A*C.

root(X,A,B,C,0,X = -B/(2*A)).

root(X,A,B,C,D,X =(-В+sqrt(D))/(2*A))  D> 0.

root(X,A,B,C,D,X = (-B-sqrt(D))/(2*A))  D> 0.

pad([(С, N) | Poly],[(C, N) | Polyl]) 

!,pad(Poly, Polyl).

pad(Poly,[(O.N) | Polyl]) 

pad (Poly, Poly1).

pad([ ],[ ]).

linear([(Coeff, 1) | Poly]).

quadratic([(Coeff,2) | Poly]).

Метод гомогенизации

homogenize ( Equation, X, Equation), X1)

Уравнение Equationс неизвестным Xпреобразуется в уравнение Equation1 снеизвестным X1,где X1-выражение, содержащее X,

homogenize(Equation, X, Equation1, X1) 

offenders (Equation, X, Offenders),

reduced_term(X, Offenders, Type, X1),

rewrite(Offenders, Type, X1, Substitutions),

substitute(Equation, Substitutions, Equation1).

offenders( Equation, Unknown, Offenders)

Offenders- множество максимальных неполиномиальных термов уравнения с неизвестным Unknown.

offendenrs(Equation, X, Offenders) 

parse(Equation, X, Offenders] \[ ]),

remove_duplicates(0ffenders1, Offenders).

multiple(Offenders).

reduced_temn(X, Offenders, Type,Xl)

classify (Offenders, X, Type),

candidate(Type, Offenders, X, X1).

Эвристики для экспоненциальных уравнений

classify (Offenders, X, exponencial) 

exponential_offenders (Offenders, X).

exponential_offenders ([AВ | Offs],X)

free_of(X,A),subterm(X,B),exponential_offenders(Offs,X).

exponential_offenders([ ],X).

candidate(exponential, Offenders, X, A | X) 

base (Offenders, A), polуnomial_exponents(Offenders, X).

base([A В| Offs], A) base(Offs, A).

base([ ],A).

polynomial_exponents([A В | Offs],X) 

is_polynomial (B, X), polynomial_exponents(Offs, X).

polynomial_exponents([ ],X).

Разбор уравнения и выполнение подстановок

parse (Expression, Term, Offenders)

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

parse(A+B,X,Ll\L2) 

!,parse(A,X,Ll\L3), parse (B,X,L3\L2).

parse(A*B,X,Ll\L2) 

!,parse(A,X,Ll\L3), parse (B,X,L3\L2).

parse(A-B,X,Ll\L2) 

! ,parse(A, X, Ll\L3), parse (B,X,L3\L2).

parse(A=B,X,L1\L2) 

!,parse(A,X,Ll\L3),parse(B,X,L3\L2).

parse(AB,X,L) 

integer(B),!, parse(A,X,L).

parse(A,X,L\L) 

free_of(X,A),!.

parse(A,X,[A | L]\L) 

subterm(X,A),!.

substitute(Equation, Substitutions, Equation1)

Список подстановок Substitutionsприменяется к уравнению Equationдля получения уравнения Equation1.

substitute(A+B, Subs, NewA+NewB) 

!, substitute(A, Subs, New A), substitute(B, Subs, NewB).

substitute(A*B, Subs, NewA*NewB) 

! ,substitute(A, Subs, NewA),substitute(B, Subs, NewB).

substitute(A-B, Subs, NewA-NewB) 

!, substitute(A, Subs, NewA), substitute (B, Subs, NewB).

substitute(A=B, Subs, NewA=NewB) 

!, substitute (A, Subs, NewA), substitute (B, Subs, NewB).

substitute(AB, Subs, NewAB) 

integer(B),!,substitute(A, Subs, NewA).

substitute(A, Subs, B) 

member(A=B, Subs),!.

substitute(A, Subs, A).

Нахождение правил преобразования в методе гомогенизации

rewrite ([Off | Offs],Type, X1, [Off = Term | Rewrites]) 

homog_axiom (Type, Off, X1, Term),

rewrite(Offs, Type, X1, Rewrites).

rewrite([ ], Type, X, [ ]).

Аксиомы гомогенизации

homog_axiom(exponential, A  (N*X),A  X, (AX)  N).

homog_axiom(exponential, A  (-X),A  X, 1/(AX)).

homog_axiom(exponential,А (Х + B), A X, A  B*A  X).

Утилиты

subterm(Sub,Term) См. программу 9.2.

position(Term,Tenn,[ ])  !.

position(Sub, Term, Path) 

compound (Term), functor(Term, F, N),

position(N, Sub, Term, Path),!.

position (N, Sub, Term, [N | Path]) 

arg(N, Term, Arg),position(Sub, Arg, Path).

position(N, Sub, Term, Path) 

N> 1,N1:=N-1, position(Nl, Sub, Term, Path).

free_of(Subterm, Term) 

occurrence (Subterm, Term, N), !,N = 0.

single_occurrence(Subterm, Term) 

occurrence(Subterm, Term, N),!,N = 1.

occurrence(Term, Term, 1) !.

occurrence (Sub, Term, N) 

compound (Term),!,functor(Term, F, M),

occurrence(M, Sub, Term, 0,N),

occurrence (Sub, Term, 0).

occurrence(M, Sub, Term, Nl, N2) 

M > 0, !,arg(M, Term, Arg),occurrence(Sub, Arg, N),

N3:=N+N1,M1:=M-l,occurrence(Ml, Sub, Term, N3,N2).

occurrence (0, Sub, Term, N, N),

multiple([Xl,X2 | Xs]).

Предположения и данные для тестирования

test_press(X,Y)  equation(X,E,U),solve_equation(E,U,Y).

equation(l, cos(x)*(l-2*sin(x))=0,x).

equation (2, x  2-3*x+2=0,x).

equation(3, 2  (2*x)-5*2  (x+ 1)+16=0,x),

Программа 22.1.Полная программа решателя уравнений

Предикат maneuver_asides (N, Equation, Equation1) состоит из двух фактов:

maneuver_sides(l, Lhs=Rhs, Lhs=Rhs).

maneuver_sides(2, Lhs=Rhs, Rhs=Lhs).

Этот предикат обеспечивает нахождение неизвестного в левой части Equationi. Первый аргумент N,голова списка позиции, указывает ту часть уравнения, в которой содержится неизвестное. Если этот параметр имеет значение 1,то не­известное содержится в левой части и сохраняется прежнее состояние уравнения. Значение параметра, равное 2,означает, что неизвестное содержится в правой части уравнения. В этом случае левая и правая части уравнения меняются местами.

Преобразование уравнения производится с помощью предиката isolate/3. При этом правила преобразования применяются до тех пор, пока не будет исчерпан список позиции:

isolate ([N | Position], Equation, IsolatedEquation) 

isolax (N, Equation, Equation 1),

isolate (Position, Equation, IsolatedEquation).

isolate ([], Equation, Equation).

Правила преобразования, или аксиомы изоляции, специфицируются посредством предиката isolax(N, Equation, Equation1).В качестве примера рассмотрим решение уравнения 1-2sin(x)=0.Эквивалентным преобразованием уравнений является добавление к обеим частям уравнения одной и той же величины. Покажем представление такого преобразования аксиомой изоляции применительно к обработке уравнений видаи-v =w. Отметим, что правила необходимы только для упрощения левых частей уравнений, поскольку гарантируется нахождение неизвестного именно в этой части.

Необходимы два правила в соответствии с возможностью нахождения неизвестного в первом или во втором аргументе терма и-v.Терми-v=wможно переписать двумя способами:и=w+vилиv=и-w.Первый аргумент предиката isolaxопределяет, какой аргумент суммы содержит неизвестное. Правила преобразования на Прологе примут вид

isolax(l, Terml-Term2=Rhs, Term1=Rhs+Term2).

isolax(2, Term1-Term2 =Rhs, Term2 =Term1-Rhs).

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

isolax(1, Term1*Term2=Rhs, Term1 = Rhs/Term2).

Однако если Term2равен нулю, то такое правило преобразования недопустима Следовательно, нужно добавить проверку, которая предотвратит применение аксиом для умножения, если терм, на который производится деление, равен нулю Например, можно записать правило

isolax (1,Term1*Term2=Rhs, Term1=Rhs/Term2) Term2 0.

Аксиомы изоляции для тригонометрических функций учитывают ситуацию, когда уравнение sin(x)=1/2,к которому мы приходим в нашем примере, имеет два решения между о и2.Варианты решения поддержаны наличием двух отдельных аксиом isolax:

isolax (1, sin(U) = V,U = arcsin(V)).

isolax (1, sin (U) = V,U = - arcsin(V)).

Общее решение уравнения можно записать, прибавив к каждому решению 2п,гдеn-произвольное целое. Решение о том, частное или общее решение требуется найти, зависит от контекста и семантической информации, независимой от решателя уравнений.

Другие примеры аксиом изоляции приведены в полном решателе уравнений (программа 22.1).

Описанная нами часть программы позволяет решать первое из представленных на рис. 22.1уравнений, а именно уравнение cos(x)*(1-2sin(x))=0.Существуют четыре ответа: arccos(0)-arccos(0), arcsin((1-0)/2), -arcsin ((1-0)/2),Каждый ответ может быть упрощен, например, arcsin((1-0)/2)= /6,но не будем этого делать, если выражение не вычисляется явно.

Полезность решателя уравнений зависит от того, насколько хорошо он сможет выполнять такое упрощение, даже если оно не является непосредственной частью задачи решения уравнения. Однако написать программу для упрощения выражений нелегко. В общем случае задача определения эквивалентности двух выражении неразрешима. Некоторые простые тождества алгебры, например правило пре­образования 0+иви, могут быть без труда включены в решатель. Выбор предпочтительной формы выражения из возможных вариантов, например (1+x) или 1+Зх+Зх2+x3 зависит от контекста.

Соседние файлы в папке prolog14_end