Creating an Expert System

See Also

Replace

Unification Pattern Matching

Authors may wish to implement collections of rewriting rules that transform algebraic expressions into new expressions by applying functional identities and relations. We will create a small expert system that applies a set of trigonometric identities transforming

sin(n*theta) and cos(n*theta) to polynomials in sines and cosines of smaller multiples of theta.

The expert system will be called Reduce, and it can serve as a model for your own ideas. To use Reduce in a book, include the prolog in the Book Script:

readlong;

precision 0;

load "algebra";

make variable ?a;

make variable ?b;

make variable ?c;

make variable ?theta;

We want the following transformations:

cos (2*k * theta) -> cos(k*theta)^2 - sin(k*theta)^2

cos( (2*k+1)*theta -> cos(k*theta) * cos ((k+1)*theta) - sin(k*theta) * sin ((k+1)*theta)

sin (2*k * theta) -> 2*sin(k*theta)*cos(k*theta)

sin( (2*k+1)*theta -> sin(k*theta) * cos ((k+1)*theta) + cos(k*theta) * sin ((k+1)*theta)

We implement these rules with
Replace using auxiliary functions: even, odd

make even(n) and( isnumber(n), n > 0, remainder(n,2) == 0);

make odd(n) and( isnumber(n), n > 1, remainder(n,2) == 1);

replace(true, cos(?a*?theta), expression, list(even(?a), cos(quotient(?a,2)*?theta)^2 - sin(quotient(?a,2)*?theta)^2 );

replace(true, cos(?a*?theta), expression, list(odd(?a), cos(quotient(?a,2)*?theta)*cos((quotient(?a,2)+1)*?theta) - sin(quotient(?a,2)*?theta)*sin((quotient(?a,2)+1)*?theta) );

replace(true, sin(?a*?theta), expression, list(even(?a), 2*sin(quotient(?a,2)*?theta)*cos(quotient(?a,2)*?theta));

replace(true, sin(?a*?theta), expression, list(odd(?a), sin(quotient(?a,2)*?theta)* cos((quotient(?a,2)+1)*?theta) + cos(quotient(?a,2)*?theta)* sin((quotient(?a,2)+1)*?theta) );

replace(true, cos(?a*?b), expression, list(?a==0,1), list(?b==0,1);

replace(true, sin(?a*?b), expression, list(?a==0,0), list(?b==0,0);

Now Reduce should start with the target expression and step through these rules until it can fire one of them. If one fires, it should continue to the end, and then step through them again. It should only halt if it goes through an entire pass without firing any rule. The function below will implement that strategy. It implements a few other rules for completeness:

Define your Expert System by copying everything below (except perhaps the name) up to the comment

' The rules that we will use follow' and then place your own rules.

program reduce (ex targexp) {

let tempexp be exact targexp;

let runexp be false;

do

until runexp == tempexp

returning tempexp

{

let runexp be exact tempexp;

' The rules that we will use follow'

let tempexp be exact replace(true, ?a*1, tempexp, list(true,?a));

let tempexp be exact replace(true, 1*?a, tempexp, list(true,?a));

let tempexp be exact replace(true, ?a*0, tempexp, list(true,0));

let tempexp be exact replace(true, 0*?a, tempexp, list(true,0));

let tempexp be exact replace(true, ?a+0, tempexp, list(true,?a));

let tempexp be exact replace(true, 0+?a, tempexp, list(true,?a));

let tempexp be exact replace(true, ?a-0, tempexp, list(true,?a));

let tempexp be exact replace(true, ?a/1, tempexp, list(true,?a));

let tempexp be exact replace(true, cos(?a*?b), tempexp, list(?a==0,1), list(?b==0,1));

let tempexp be exact replace(true, sin(?a*?b), tempexp, list(?a==0,0), list(?b==0,0));

let tempexp be exact replace(true, cos(?a*?theta), tempexp, list(even(?a),

cos(quotient(?a,2)*?theta)^2 - sin(quotient(?a,2)*?theta)^2 ));

let tempexp be exact replace(true, cos(?a*?theta), tempexp, list(odd(?a),

cos(quotient(?a,2)*?theta)*cos((quotient(?a,2)+1)*?theta) -

sin(quotient(?a,2)*?theta)*sin((quotient(?a,2)+1)*?theta) ));

let tempexp be exact replace(true, sin(?a*?theta), tempexp, list(even(?a),

2*sin(quotient(?a,2)*?theta)*cos(quotient(?a,2)*?theta)));

let tempexp be exact replace(true, sin(?a*?theta), tempexp, list(odd(?a),

sin(quotient(?a,2)*?theta)* cos((quotient(?a,2)+1)*?theta) + cos(quotient(?a,2)*?theta)*

sin((quotient(?a,2)+1)*?theta) ));

}

}

The Reduce Program is a small expert system, and any script that needs it can simply call it as a function with the expression to simplify.

For example, with a Math Edit Window and a Command line, if you type:

Output "/p", Reduce( cos(2*t) )

cos(t)^2 - sin(t)^2 is printed

Output "/p", Reduce( cos(3*t) )

cos(t)^3 - 3*cos(t)*sin(t)^2 is printed

Output "/p", Reduce( cos(4*t) )

cos(t)^4 - 6*cos(t)^2*sin(t)^2 + sin(t)^4 is printed

Output "/p", Reduce( sin(2*t) )

2*sin(t)*cos(t) is printed

Output "/p", Reduce( sin(3*t) )

  1. sin(t)*cos(t)^2 - sin(t)^3 is printed

Output "/p", Reduce( sin(16*t) )

16*sin(t)*(cos(t))^15 - 560*(sin(t))^3*(cos(t))^13 + 4368*(sin(t))^5*(cos(t))^11 -11440*(sin(t))^7*(cos(t))^9 + 11440*(sin(t))^9*(cos(t))^7 - 4368*(sin(t))^11*(cos(t))^5 + 560*(sin(t))^13*(cos(t))^3 - 16*(sin(t))^15*cos(t)

is printed!