Functions, Variables, and Equations
1 Variables
If you type any letter, such as x, or t, or p, in a Maxima command, it automatically interprets it as a variable.
But what if you want to make a variable have a specific value? Let's say we are doing a
problem that has a constant R that is defined to be 3.75, and all of the calculations we
need to do are written using R. It would be nice to set R=3.75 and then use R in our
calculations. Let's try this in the most obvious way:
--> R=3.75;
(%o1) R = 3.75
O.k., that looks pretty good. But watch what happens if we try to get back the value of R:
--> R;
(%o5) R
Or try to do a calculation with R:
--> %pi*R^2;
(%o2) πR 2
Wait... this isn't really what we want! The issue is that Maxima uses = for equations, *not* for
setting values. The way to set a value in Maxima is to use a colon (:), which is called -binding-
--> R:3.75;
(%o9) 3.75
--> %pi*R^2;
(%o3) πR 2
--> A:%pi*R^2; float(A);
(A) πR 2
(%o5) 3.141592653589793R 2
1.1 Killing a Variable
Now, if we want to use R or A to represent a different value later on, we have two options:
1) We can redefine R and A using (:) again.
2) We can kill them.
You read that right. Maxima is a violent language (things were rougher in the 1960's...) To free up a variable
so that you can use it somewhere else, we kill it like so:
--> kill(A);
https://www.scotchildress.com/wxmaxima/Variables_Functions_Equations/Variables_Functions_and_Equations.html 27/08/24, 10 08 PM
Page 1 of 10
:
(%o22) done
--> A;
(%o23) A
--> kill(R);R;
(%o20) done
(%o21) R
We can kill multiple variables at once:
--> A:35.7;R=%pi/%e;
(%o24) 35.7
(%o25) R = %e−1 π
--> kill(A,R);
(%o26) done
--> A; R;
(%o27) A
(%o28) R
You can use kill to free up ANY object that you create in Maxima - not just variables!
Finally, you can kill all variables that have been assigned in a given session by typing:
--> kill(all);
(%o0) done
2 Functions
Let's say that we want to define a function f(x) = 2x+7. We just saw that using = doesn't cut it.
What if we try (:)
--> f(x):2*x+7;
assignment: cannot assign to f(x) -- an error. To debug this try: debugmode(true);
Hrmm... That's frustrating. The issue here is the same issue that we encountered when we tried to
multiply using ()'s. Maxima is programmed to read () as a function - even though we are in the
process of trying to define f(x)! Maxima has a special symbol for function definitions, it is the
same symbol used frequently in Computer Science Textbooks to define values: it is a colon followed by
and equal sign (:=)
--> f(x):=2*x+7;
(%o6) f(x) := 2x + 7
--> f(x);
(%o7) 2x + 7
--> f(3);f(2.56); f(%e);
(%o8) 13
https://www.scotchildress.com/wxmaxima/Variables_Functions_Equations/Variables_Functions_and_Equations.html 27/08/24, 10 08 PM
Page 2 of 10
:
(%o9) 12.12
(%o10) 2%e + 7
Nice! Any arithmetic or built in function can be used in a function definition, and any letter can be used for the variable:
--> g(y):=sin(y)/(log(y)+y^2);
sin (y)
(%o11) g(y) :=
log (y) + y 2
--> g(%pi);
g(%pi/2);
g(x);
(%o12) 0
1
(%o13) 2
log ( π2 ) + π4
sin (x)
(%o14)
log (x) + x2
The nice thing about Maxima's insistence on treating all letters as variables is that if you type in something like:
--> g(3*x+7);
sin (3x + 7)
(%o16)
log (3x + 7) + (3x + 7)2
Maxima is smart enough to do the right thing and make a composition. Speaking of compositions, they work exactly like
they should:
--> f(x):=3*x+7; h(x):=g(f(x));
(%o20) f(x) := 3x + 7
(%o21) h(x) := g(f(x))
--> h(x);
sin (3x + 7)
(%o22)
log (3x + 7) + (3x + 7)2
--> h(3);
sin (16)
(%o23)
log (16) + 256
Not too bad! Now that we are done with f(x), g(x), and h(x), let's kill 'em:
--> kill(f,g,h);
(%o24) done
2.1 The define() Command for Function Definition
There is another way to define a function that comes in really handy when working with symbolic expressions.
Let's start with an expression in x:
--> E:x^3-2*x*sin(x);
(E) x3 − 2x sin (x)
https://www.scotchildress.com/wxmaxima/Variables_Functions_Equations/Variables_Functions_and_Equations.html 27/08/24, 10 08 PM
Page 3 of 10
:
O.k., that looks pretty good and for calculations like:
--> expand(E^3-2*E+E^2);
(%o26) −8x3 sin (x)3 + 12x5 sin (x)2 + 4x2 sin (x)2 − 6x7 sin (x) − 4x4 sin (x) + 4x sin (x) + x9 + x6 − 2x3
It works just fine. But what if you wanted to evalute E for x=%pi? Let's give it a try:
--> E(%pi);
apply: found E evaluates to x3 − 2x sin (x) where a function was expected. -- an error. To debug this try: debugmode(true);
The problem here is that E is an -expression- not a function. We can substitute values into an expression
using subst() like so:
--> subst(x=%pi,E);
(%o28) π 3
But what we really need is a way to elevate E to a function. This will become even more important later
when we want to "catch" the results of integration and differentiation as functions and not symbolic
expressions. The solution is the command define(), and we use it like so:
--> define(fE(x),E);
(%o29) fE(x) := x3 − 2x sin (x)
Note that the function has to spell out the fact that x is the dependent variable in the notation fE(x). Now we have the -functional- version fE(x) of E that is
a genuine function:
--> fE(%pi); fE(%pi/2);
(%o32) π 3
π3
(%o33) −π
8
--> trigexpand(expand(fE(x+1)));
(%o35) −2x (cos (1) sin (x) + sin (1) cos (x)) − 2 (cos (1) sin (x) + sin (1) cos (x)) + x3 + 3x2 + 3x + 1
Finally we mention that define() can be used directly as follows:
--> define(F(x),x+5);
(%o36) F(x) := x + 5
--> kill(all);
(%o0) done
2.2 Lazy Use of define()
It is tempting to want to be economical and write something like:
--> E:x^2+2*x+7;
(E) x2 + 2x + 7
--> define(E(x),E);
(%o2) E(x) := x2 + 2x + 7
https://www.scotchildress.com/wxmaxima/Variables_Functions_Equations/Variables_Functions_and_Equations.html 27/08/24, 10 08 PM
Page 4 of 10
:
Note that this does indeed work:
--> E(x); E(2);
(%o3) x2 + 2x + 7
(%o4) 15
--> subst(x=2,E);
(%o5) 15
--> E;expand(E(x+3));
(%o7) x2 + 2x + 7
(%o8) x2 + 8x + 22
But note that E is now a function, and not a symbolic expression. Most of the time
this will not cause any serious issues, but we note it here just in case.
--> kill(all);
(%o0) done
3 Equations
3.1 Defining and Working With Equations
We saw that wxMaxima reserves = for use in equations. A cool feature is that we can actually write
down an equation and assign a name for it!
--> E:x^2 = 4;
(E) x2 = 4
--> E;
(%o2) x2 = 4
--> F:2*x - 5 = 7;
(F) 2x − 5 = 7
Why would you want to name an equation?! Well, this makes it easier to work with (we'll see this later on)
but we can also do some pretty cool algebra. For example, let's say I wanted to add equation E to F and see the
result. Here's how it works in Maxima:
--> E+F;
(%o16) x2 + 2x − 5 = 11
Which is nice, because this is precisely the obvious thing to do. So what about a more complicated combination like:
Square both sides of F:
--> F^2;
(%o17) (2x − 5)2 = 49
Or, square root both sides of F and subtract three times E:
--> sqrt(F) - 3*E;
https://www.scotchildress.com/wxmaxima/Variables_Functions_Equations/Variables_Functions_and_Equations.html 27/08/24, 10 08 PM
Page 5 of 10
:
–
(%o18) √−−−−
2x −−5 − 3x2 = √7 − 12
You have to admit, that's pretty neat. One last thing. What if we want just the right hand side of an equation, or the left hand side?
Maxima has functions rhs() and lhs() that grab the left and right hand sides of equations:
--> G:x^2+2*x = 4*sin(x); rhs(G); lhs(G);
(G) x2 + 2x = 4 sin (x)
(%o11) 4 sin (x)
(%o12) x2 + 2x
Let's say that we want to grab the right hand side of G and use it as its own function rG(x).
We can do that easily!
--> define(rG(x),rhs(G));rG(x);rG(%pi/3);
(%o6) rG(x) := 4 sin (x)
(%o7) 4 sin (x)
–
(%o8) 2√3
Let's clean up our mess and move on:
--> kill(E,F,G);
(%o104) done
3.2 Solving Equations
One of the main reasons computer algebra systems like Maxima were created was to simplify the task of
solving tedious equations. Maxima has a built in function called solve() that does this:
--> solve(3*x-7=15,x);
22
(%o9) [x = ]
3
--> solve(x^2 - 3*x + 3=0,x);
– –
√3%i − 3 3 + √3%i
(%o64) [x = − ,x = ]
2 2
The %i here represents sqrt(-1), the complex unit.
So we see that the solve function takes in an equation as the first input and the variable we want to solve for as the second. It returns a list of all the
solutions. Why do we have to specify a variable? Because Maxima can solve equations that
only are written using variables!
--> solve(P=2*(L+W),L);
2W − P
(%o21) [L = − ]
2
--> solve(P=2*(L+W),W);
P − 2L
(%o20) [W = ]
2
--> solve(A = %pi*r^2, r);
−− −−
√ √
https://www.scotchildress.com/wxmaxima/Variables_Functions_Equations/Variables_Functions_and_Equations.html 27/08/24, 10 08 PM
Page 6 of 10
:
−
− −
−
√A √A
(%o19) [r = − − ,r = −]
√π √π
--> solve(A=(1/2)*h*(a+b), a);
2A − bh
(%o22) [a = ]
h
--> solve(a*x^2 + b*x + c=0,x);
−−−−−−− −−−−−−−
√b2 − 4ac + b √b2 − 4ac − b
(%o23) [x = − ,x = ]
2a 2a
O.k., so that's already pretty cool, but it gets better. Let's say we have a function f(x) = 3*x^2 - 2*x and want to know
when f(x) = 7. We can do the obvious thing:
--> f(x):=3*x^2-2*x;
(%o68) f(x) := 3x2 − 2x
--> solve(f(x)=7,x);
√−−
22 − 1
−−
1 + √22
(%o69) [x = − ,x = ]
3 3
Or, we can find the values of x for which our function f(x) and some other function g(x) are equal:
--> g(x):=3*x^3 - 2*x^2;
(%o70) g(x) := 3x3 − 2x2
--> solve(f(x)=g(x),x);
2
(%o71) [x = 1, x = , x = 0]
3
--> kill(f,g);
(%o72) done
Recall that we can name equations. This can make things really nice:
--> E:3*x^2 = 2*x; F:3*x^3 = 2*x;
(%o3) 3x2 = 2x
(%o4) 3x3 = 2x
--> E-F;solve(E-F,x);
(%o5) 3x2 − 3x3 = 0
(%o6) [x = 0, x = 1]
--> kill(E,F);
(%o79) done
If you type in a function into solve() instead of an equation - like solve(f(x)), then solve() solves f(x) = 0 for x.
--> solve(x^3 + 3*x^2 - 5);
√3%i
− 1 – 1 – – 1 – − 12 − 2
√3%i – 1
3 √5 3 1 √3%i 3 √5 3 √3%i 1 3 √5 3
(%o83) [x = 2 2
+( + ) (− − ) − 1, x = ( + ) ( − )+ − 1, x = ( + ) +
1
2 2 2 2 2 2 2 2 1
2 2
( 32 + ) ( 32 + 2 ) ( + )
√5 3 √5 3
2
https://www.scotchildress.com/wxmaxima/Variables_Functions_Equations/Variables_Functions_and_Equations.html 27/08/24, 10 08 PM
Page 7 of 10
:
Yuck! It's nice we did not have to go and calculate all of that! But now that we have this list, what if I want to use one of
the solutions, but I don't want to type it in? Here's how we do it: "Catch" the solutions by assigning a name to them:
--> L:solve(x^3+3*x^2-5)$
--> L;
√3%i
− 1 – 1 – – 1 – − 12 − 2
√3%i – 1
3 √5 3 1 √3%i 3 √5 3 √3%i 1 3 √5 3
(%o88) [x = 2 2
+( + ) (− − ) − 1, x = ( + ) ( − )+ − 1, x = ( + ) +
1
2 2 2 2 2 2 2 2 1
2 2
( 32 + ) ( 32 + 2 ) ( + )
√5 3 √5 3
2
Now to get each of these solutions, we type:
--> L[1];
√3%i
− 1 – 1 –
3 √5 3 1 √3%i
(%o89) x = 2 2
+( + ) (− − )−1
1
2 2 2 2
( 32 + )
√5 3
2
--> L[2];
– 1 – − 12 − 2
√3%i
3 √5 3 √3%i 1
(%o90) x = ( + ) ( − )+ −1
2 2 2 2 1
( 32 + 2 )
√5 3
--> L[3];
– 1
3 √5 3 1
(%o91) x = ( + ) + −1
2 2 1
( 32 + )
√5 3
2
Now, that's great, but what if we want, for instance, the actual value contained in L[3]? Typing
L[3] gives back an equation, not the value. To get the value, we use rhs():
--> rhs(L[3]);float(rhs(L[3]));
– 1
3 √5 3 1
(%o106) ( + ) + −1
2 2 1
( 32 )
√5 3
+ 2
(%o107) 1.103803402735536
I will be the first to admit that this is a little goofy, but this is one of the challenges that faces
us when we use technology to solve problems. The computer can only give back the
solutions in the form that it is programmed to give it, and it is up to us to extract the information
that we want.
--> kill(L);
(%o108) done
3.3 Solving Equations with Radicals
Often we come across equations with radicals in them, like:
--> E:sqrt(x)=sqrt(8-x);
x = √−
(E) √− 8−−
−−−
x
And we would like to solve them. But notice that when we attempt to use solve() we get:
--> solve(E,x);
https://www.scotchildress.com/wxmaxima/Variables_Functions_Equations/Variables_Functions_and_Equations.html 27/08/24, 10 08 PM
Page 8 of 10
:
x = √−
(%o7) [√− 8−−
−−−
x]
Which is really not helpful. The problem is that Maxima views the radical expressions are variable quantities in their own right, and thus it thinks that it
did solve the equation. To get around this
we use a more powerful version of solve() called to_poly_solve() that converts radical equations to
polynomial equations first before solving.
To use to_poly_solve() we first have to load it:
--> load(to_poly_solve);
Loading maxima-grobner $ Revision: 1.6 $ $ Date: 2009-06-02 07:49:49 $
(%o24) /usr/share/maxima/5.32.1/share/to_poly_solve/to_poly_solve. mac
and then:
--> to_poly_solve(E,x);
to\_ poly\_ solve: to\_ poly\_ solver.mac is obsolete; I'm loading to\_ poly\_ solve.mac instead.
(%o26) %union([x = 4])
Unlike solve(), you *must* indicate the variable that you are solving for!
Let's solve another:
--> kill(E);
(%o27) done
--> E:sqrt(2*x-1)+sqrt(x) = 3;
(E) √−−−−
2x −−1 + √−
x =3
--> to_poly_solve(E,x);
−−
(%o44) %union([x = 28 − 6√19 ])
So what's the deal with %union? This is telling us that the solutions form a set comprised on the elements in the
union. To get the elements out of the union, we use the part() function like so:
--> E:x^2=4;
(E) x2 = 4
--> S:to_poly_solve(E,x);
(S) %union([x = −2], [x = 2])
--> part(S,1,1);part(S,2,1);
(%o49) x = −2
(%o50) x = 2
We can further extract the values using rhs() and lhs() for use!
--> kill(all);
(%o0) done
3.4 Solving an Equation and Substituting the Result
https://www.scotchildress.com/wxmaxima/Variables_Functions_Equations/Variables_Functions_and_Equations.html 27/08/24, 10 08 PM
Page 9 of 10
:
MANY times in Algebra, we need to solve an equation, and then turn around and substitute our solution into
another formula. In Maxima, the function: subst() does substitution for us.
--> subst(x=3, x^2 + 1);
(%o109) 10
Admittedly, in this context, subst() seems pretty lame. But let's take a look at how this can be *really* useful.
Imagine a problem where the radius of a sphere is found by solving: 2*R^3 - 5*R = 7. So let's solve to find the
radius, and then use the radius to find the volume of the sphere!
--> r:solve(2*R^3-5*R=7,R);
5( − 12 ) 5 (− 2 − 12 )
√3%i 1 1 √3%i
−−−− – −−−− – −−−−
+( + ) (− − ),R = ( ) ,R = ( ) +
√1073 7 3 √3%i 1 √1073 7 3 √3%i 1 √1073
( )
2
(r) [R = + − + +
1
43 2
3
4 2 2 3
43 2 4 2 2 1 3
43 2
) 6( 3 + 4 )
3 3
√1073 7 √1073 7
6( 3 + 4
43 2 43 2
Taking a look at these solutions, it looks like the third one is the only real solution. Let's use the fact that
--> r[3];
1
−−−−
(%o2) R = ( + ) +
√1073 7 3 5
43 2
3
4 1
+ 74 )
3
√1073
6( 3
43 2
gives the value of R in an equation that subst() can use:
--> subst(r[3],(4/3)*%pi*R^3);
⎛ ⎞
3
⎜ ⎟
4⎜ ⎟π
1
⎜( 3 + 74 ) + ⎟
3
√1073
⎜ 43 2 ⎟
5
⎜ ⎟
1
⎛ √1073 7 ⎞ 3
⎝ 6
⎝ 3
+
4⎠ ⎠
43 2
(%o3)
3
--> float(subst(r[3],(4/3)*%pi*R^3));
(%o4) 36.1385405321193
So, even though giving solutions as equations seems a little awkward, there is good reason for it!
As a parting thought, we can streamline a lot of the work that we just did, provided we already
know (by doing the calculation above) yields the real solution:
--> float(subst(solve(2*R^3-5*R=7,R)[3],(4/3)*%pi*R^3));
(%o5) 36.1385405321193
The above is a demonstration of the real power of a CAS, but please do note that the above is
very difficult to read. If you have the option of solving something in one very complicated
line of dense expressions, or using several, easy to understand calculations - it is always
better to do the latter.
--> kill(all);
(%o0) done
Created with wxMaxima.
https://www.scotchildress.com/wxmaxima/Variables_Functions_Equations/Variables_Functions_and_Equations.html 27/08/24, 10 08 PM
Page 10 of 10
: