This workbook contains the wxMaxima commands that appear in 
Sections 5 and 6 of Chapter 1.

The cell below is optional. The purpose of each of the commands
is indicated in the final section of Chapter 1 in the text.

load(draw)$ 
set_draw_defaults(  fill_color=gray40,
draw_realpart=false,font_size=10)$
fpprintprec:5$ ratprint:false$kill(all)$

# Chapter 1. Introduction

## Basics

## The wxMaxima Screen

## Mathematical Functions

## Referring to and Evaluating Expressions

## Sequences, Lists, and Sets 

A list appears as sequence enclosed by square brackets, as in 
these three examples.  The list need not be bound to a name, 
but such binding can be useful if terms are to be used 
later in the session.

kill(all)$   list1:[a,a,b,c,d,1,2,2,7,9,9,"x = 2"];
list2 : makelist(j^2, j, 1, 7);
list3 : realroots( (1 + 2*x)^3 = 12*(1 + x^5) );

One a list is created, its contents can be accessed. The
examples below are from the text. Note that the second 
command extracts an item from the list, then extracts 
the right-hand side (rhs) of that item, and finally
produces a floating point representation of that value. 

rhs(list3[2]);   float(rhs(list3[2]));

The next cell decomposes these three steps, using %.

list3[2]; rhs(%); rhs(%);

A set appears as a sequence enclosed by braces--{}. 
Two differences distinguish lists from sets. First, a list 
is strictly ordered, whereas the order of elements within a 
set is arbitrary. This distinction shows up in a number of 
places in Maxima. For example, as in list3 
above, Maxima returns a set of solutions for the 
unknown values. The ordering of the items in the solution set is 
internally determined by Maxima. The order matters, 
for it allows reference to specific items in the list. 

The second difference between a list and a set is that 
a set does not contain duplicated elements, whereas 
two or more elements of a list may be identical. Maxima 
eliminates duplicate elements in a set. The setify( ) 
command converts a list to a set.

set1:{1,1,1,2,4,5,a,b,b,c};  set2:setify(list1);

Lists can be used to bind variable names to values. 

kill(all)$  [a,b,c,d]:[1,exp(2),"some text",sin(x)];
[a, float(b),subst(x=%pi/4,d)];

As noted above and illustrated once more in the first example
below, expressions may be used to create a list of values. The
makelist( ) command, introduced here, is used many times in 
later material, especially in the production of tables.

kill(all)$  makelist(sin(i*%pi/4),i,0,8);

One attraction of using f(x) to define an expression
is that it provides an easy way to evaluate f(x) for a
list of x values, producing a list of f(x) values.
Note that the second and third lists contain the same
values.

The fpprintprec command is used to ensure that the table 
is not excessively wide.  The matrix( ) command is used 
to convert a set of three lists into a table. Later, 
we will add headings to tables, also using matrix( ).

kill(all)$ fpprintprec:5$  f(t):=2*exp(0.05*t)$  
tList:makelist(10*i,i,0,5)$ fList:map(f,tList)$
fList2: f(tList)$  matrix(tList,fList,fList2);

## Solving Equations

Maxima can solve many types of equations andsets of equations. 
The syntax of the solve command is direct: enter the 
expression(s) to be solved and then the variable(s) for which it is
(they are) to be solved.

### Single Equation

Solve f(x)= 0 for x, assigning the name solnf to the solution.
Then solve the expression A*x^2 + B*x + C for x by entering 
the expression directly.

Finally, solve the expression bound to the name z, 5*x^2-500.
Note that Maxima treats + -500 as adding -500 to 5*x^2. The
+ sign could be omitted.

Each expression is entered into a list along with the command
that solves it and assigns the solution a name.
The second name is soln_exp. The underline character avoids a
break in the name. The name soln exp, with a space, is not a 
valid Maxima name.

kill(all)$   [f(x):=(x-a)^2/(x+b),solnf:solve(f(x),x)];
soln_exp: solve(A*x^2 + B*x + C, x);
[z: 5*x^2 + - 500, solnz: solve(z, x)];

We can confirm that the solution of f(x) above is correct in
either of two equivalent ways.

[f(a), f(rhs(solnf[1]))];

The subst( ) command is handy when solutions are being 
evaluated.

[sol1:subst(rhs(soln_exp[1]),x,A*x^2+B*x+C),
      ratsimp(sol1)];
[sol2:subst(soln_exp[2],A*x^2+B*x+C),ratsimp(sol2)];

The ev( ) command can be used, but we prefer the subst( ) 
command.

[ev(z,x=-10),   ev(z, solnz[2])];

### Evaluating Expressions

To determine a numeric value for f(x), given values of a, b, 
and x, rephrase the function as below. The matrix( ) command used
to build the table in the text is removed and replaced by 
a set of print( ) commands. 

The print commands end with $. Replace the $ with ; to determine
how the output changes.

kill(all)$     
print("The function: ",f(x,a,b):=(x-a)^2/(x+b))$
print("The function, with parameters: " ,f(x,5,4))$
print("The function's value : ",f(-2,5,4))$ 
print("The function's value, floating point:  ",f(-2.0, 5, 4))$

Observe that f(x,a,b) is not defined when x = -b. The 
graph below shows how the expression behaves when a = 5 and
b = 4. Don't worry about the wxdraw2d( ) command. We develop
it in detail at the end of this workbook.

wxdraw2d(yrange=[-150,150],xaxis=true,yaxis=true,
color=blue,
explicit(f(x,5,4),x,-10,5), color=black,
point_size=2,points([ [-2,f(-2,5,4)] ]))$

### Systems of Equations

Systems of equations are solved the same way as single
equations, except that lists of expressions and lists
of variables must be entered.

kill(all)$  expr1:2*a*x+4*y-10*z$
expr2:2*x-y+2*z=25$  expr3:2*x+3*y-z=0$
sol : solve([expr1,expr2,expr3],[x,y,z]);

We could have defined a list name such that only the
embedded list constitutes the output. The next cell 
illustrates this. To keep references consistent with the
text, we do not bind a name to this result. It is here
to show that the option exists.

solve([expr1,expr2,expr3],[x,y,z])[1];

Now we confirm the solution above. That the second 
expression is correct is not obvious, but using the 
ratsimp( ) command to simplify the expression confirms
the result. 

subst([sol[1]],[expr1,expr2,expr3]);
transpose(matrix(%));  ratsimp(%);

The transpose(matrix( )) command can be omitted.

subst([sol[1]],[expr1,expr2,expr3]);
ratsimp(%);

Also, we could embed the results of subst( ) into ratsim( ),
reducing the command to a single statement.

ratsimp(subst([sol[1]],[expr1,expr2,expr3]));

We can solve the system of equations for a given value for a.

subst(5.0,a,sol);

### Numerical Methods

The solve command can deal with many equations, 
but fails when Maxima does not recognize the equation type
and, perforce, when no solution exists. When a symbolic solution
cannot be found, we can seek a numeric approximation to the 
solution. We consider two ways of achieving this result for
single equations: find_root( ) and newton1( ). For systems of
equations, we consider mnewton( ), a counterpart to newton1( ).

A Unique Solution

Any expression may have no solutions, a single solution, or 
mulitple solution. The next example has a single solution.
The attempt to apply solve( ) fails in this case.

kill(all)$  [pd(x):= 12*x^(1/(-2.5)),ps(x):=5+2*x];
solve(pd(x)-ps(x), x);

Drawing a graph often helps. As before, take this command as 
given, without concern about its syntax.

wxdraw2d(yrange=[0,20],explicit(pd(x),x,0.5,5),
color=blue,explicit(ps(x),x,0,5))$

The next cell sets the precision with which the output is printed.
Then it makes three attempts to apply find_root( ). All but the 
last fail, for reasons discussed in the text.

fpprintprec:16$  
find_root(pd(x)-ps(x),0,4);  /*Cannot evaluate at x=0*/
find_root(pd(x)-ps(x),0.1,1.5); /*x range is too short--
                                             does not include the critical value*/
find_root(pd(x)-ps(x),0.1,4); /*Works. Don't end a cell with a comment*/  end$

The newton1( ) method yields a result that appears close to the
one derived above, but the two differ.

load(newton1)$  newton(pd(x)-ps(x),x,2,.00001);

Multiple Solutions

A quadratic equation can have two roots, like the one below.
(Confirm that -4*x^2 +100*x-625 has one root and -4*x^2 +100*x-700
has no roots.)

P: -4*x^2 +100*x-200$ wxdraw2d(xaxis=true,explicit(P,x,0,25))$
/*   P: -4*x^2 +100*x-625$ wxdraw2d(xaxis=true,explicit(P,x,0,25))$
P: -4*x^2 +100*x-700$ wxdraw2d(xaxis=true,explicit(P,x,0,25))$  */ end$

Either find_root or newton will return a different
solution depending on the specification. With find_root, 
endpoints must be specified. First, search over the
range 0.1 <= x  <= 5  and then over the range 3 <= x  <= 30. 
The list in the text is replaced with two print( ) commands.

print("1st root, x = ",find_root(P,0.1,5))$
print("2nd root, x = " ,find_root(P, 3, 30))$

The first newton command set x below the lower value 
at which f(x) = 0, using the graph for guidance. The second 
command sets x above the upper value at which f(x) = 0.
This time, the list used in the text is replaced by a matrix( )
command.

matrix(["First root, x", "Second root, x"],
[newton(P, x, 0.5, .0001), newton(P, x, 25, .0001)  ]);

Systems of Equations
An important attraction of the Newton method is that it extends to 
systems of equations. As with newton1( ), a graph is used to 
guide the application of mnewton( ).

The graph has been changed in two ways from the one the text.
The key has been moved to the left, and the g(x,y) graph is blue.

Again, you needn't be concerned with how these changes are 
made until later.

kill(all)$  
[f(x, y):=x+3*log(x)-y^2, g(x,y):=2*x^2-x*y-5*x+1];
wxdraw2d(user_preamble="set key top left",
xaxis=true,xlabel="x",key="f(x,y)", 
implicit(f(x,y),x,0.01,5,y,-5,5),color=blue,
line_width=2, key="g(x,y)",
implicit(g(x,y),x,0,5,y, -5,5))$

Load the package mnewton and execute mnewton( ). The output
list in the text is replaced by a pair of print( ) commands. Note the
use of [1] to extract the list of solutions from the list within which 
it was embedded. If you're not sure about what is done here,
copy the cell below by clicking on the bracket at the left and 
selecting Copy. Then paste it either above or below the cell,
remove the [1] from each line, and execute the commands 
once more.

load("mnewton")$ fpprintprec:5$  
print("One pair of critical values is ", mnewton(  [f(x,y),g(x,y)],[x,y],[3,2])[1])$
print("The other pair is ", mnewton([f(x,y),g(x,y)],[x,y],[2,-1])[1])$