1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174

Why $x^(1)$ and $1/x$ are not the same in Yacas
Wouldn't it be wonderful if we had a program that could do all
the mathematical problems for us we could ever need? Need to
solve a set of equations? Just call {Solve} with the appropriate
arguments. Want to simplify an expression? Just call {Simplify}
and you will always get the form you would like to see.
A program, simply, that could replace any mathematician. An
expert system, the domain of expertise being mathematics.
Wouldn't that be great?
The answer to the above is, at least according to the author,
a resounding no. It is doubtful such a program will ever exist,
but it is not even sure that such a program would be desirable.
Humans have a long history of making tools to make their lives
easier. One important property of a tool is that it is clear
conceptually to the user of that tool what that tool does.
A tool should not be clever. The user of the tool can be clever
about using the tool, or combining it with other tools.
A 'clever' tool often results in a tool that is not useful.
It is hard to understand what a clever tool does, or why
it does what it does. In short: its behavior will be unpredictable.
This is a passionate plea against generic commands like {Simplify}
and {Solve}.
Consider this bit of interaction in {Yacas}:
In> a:= x^(1)
Out> x^(1);
In> b:= 1/x
Out> (1)/x;
In> a = b
Out> False;
Now, that can not be right, can it? Clearly, these are the same?
No, they are not. They have a slightly different form, and are
thus represented differently internally. the {=} sign compares
the internal representation of two expressions , so {a = b} returns
{False} because the internal representations of the expressions
{a} and {b} are bound to are different. Note that this is behaviour
that is simple to explain. The {=} operator is a 'tool', it is
simple, and does one thing but does it well. It is easy to use,
an important property of a tool.
To drive home this point further, suppose we did modify the
{=} operator to detect that {a} and {b} are indeed equal.
Great! Wonderful! {a=b} now returns {True}. But consider
In> c:=1+r+r^2
Out> r+r^2+1;
In> d:=(1r^3)/(1r)
Out> (1r^3)/(1r);
In> c=d
Out> False;
{c} and {d} are equal for all values of {r} where {r != 1},
but there a limit can be taken:
In> Limit(r,1)d
Out> 3;
In> Limit(r,1)c
Out> 3;
Now, we have to modify the
{=} tool to also detect that these are the same. Actually,
this will have to be done for all known identities! Or we
shall have to explain for which expressions it can determine
equality. This will be a complex story, it will be hard to
explain. It will be a complex tool to use. And, more practically,
it will be a slow tool.
So, how do we go about verifying that {a} and {b} are the same?
Or that {c} and {d} are the same?
The solution lies in devising new tools.
Canonical and normal representations
A <i>canonical</i> representation for a group of expressions
is a representation for each object in that group such
that if two elements of the group are the same, they
also have the same (internal) representation. Thus, when
expressions are brought to their canonical representations,
the {=} tool can be used to verify that they are the same.
A representation is called a <i>normal</i> representation if zero
only has one representation. Thus {nf(ab)=0} should be
something that should return {True} if {a} and {b} are
the same mathematically.
Consider a normal form defined on rational functions:
In> MM(a)
Out> MultiNomial({x},{{1,1}});
In> MM(b)
Out> MultiNomial({x},{{0,1}})/
MultiNomial({x},{{1,1}});
However:
In> MM(ab)
Out> MultiNomial({x},{{0,0}})/
MultiNomial({x},{{1,1}});
In> NormalForm(%)
Out> 0;
So here we have found a <i>combination</i> of tools that together
allow us to decide that the {a} and {b} defined in the
beginning of this section are the same: convert {ab} to
a normal form of {ab}, and verify with the {=} tool that
they are the same:
In> NormalForm(MM(ab)) = 0
Out> True;
Now consider the {c} and {d} defined above. {c} and {d} are
both functions of {r} only, $ c = c(r) $ and $ d = d(r) $.
Now, let us define a function $ f(r) = c(r)  d(r) $:
In> f(r):=Eval(cd)
Out> True;
In> f(r)
Out> r+r^2+1(1r^3)/(1r);
It is not quite clear yet that this is zero. But we can decide
that this is zero (and thus {c(r)=d(r)}) by first noting that
$ f(r) $ is zero for some r, and then that the first derivative
of $ f(r) $ with respect to $ r $ is zero, independent of r:
In> f(0)
Out> 0;
In> D(r)f(r)
Out> 2*r+1(((1r)*3*r^2+r^31))/(1r)^2;
In> NormalForm(MM(%))
Out> 0;
So here we have avoided bringing {c} and {d} to canonical forms,
by for example first discovering that {c} is a geometric series,
and gone straight to detecting that {cd} is in fact zero, and
thus $ c(r)=d(r) $.
Here again we have combined tools that are simple, do one thing
but do it well, and for which it is easy to understand for human
beings what they do.
But how can we then build a powerful CAS?
A new problem is introduced when algorithms are written down
that require more powerful comparison tools, tools that are
more sophisticated than the {=} tool for detecting that two
expressions are indeed the same. The solution to this is to
write the algorithm, but leave the actual comparison tool
to be used by the algorithm configurable. This makes
algorithms more flexible: the comparison operator can be
passed in as an argument, or the algorithm can perhaps detect
to which group its arguments belong, and use the appropriate
tool to detect equality between two expressions.
Conclusion
A CAS (or any other system built to be used by humans for that
matter) should be built up from small, well understood building
blocks. Yacas contains hundreds of functions that can be combined
into more powerful algorithms. These tools are documented in the
documentation that comes with Yacas. Yacas solves the problem in
that way. Let the user be smart, and choose the tools he needs
based on understanding what the tools do. Large, complicated,
cumbersome calculations can be done that way by just using
well understood tools and combining them appropriately.
