On 12/6/06, William Stein <wst...@gmail.com> wrote:
>
> Sage calculus
> f = alg expr
>
> f.subs(var, val, ...)
> f.subs(dict)
> f.subs(list of pairs)
> implement recursively, with base case functions of 1 var and vars and
> constants being clear.
>
> f.function(*args) - returns a callable version of f, which otherwise
> works in same way. Output is result of subs.
> this just another formal function, but with a call method.
> Also, function((vars...),expr) makes an evaluatable function.
>
> f.derivative(var) - we completely implement.
>
> f.integral(var, optional endpoints) - feed expr to maxima (or maple or
> mathematica or mathomatic or yaccas or??) and let it compute integral
> symbolically. Sage_eval the result (if possible - if that fails,
> maybe wrap the external object formally).
>
> Basic functions: all functions like sin, cos, exp, special funcs,
> etc, will be defined as formal functions - a lot of this is already
> done.
>
> >
>
>
> This is brilliant, IMHO.
>
>
> On 12/6/06, William Stein <wst...@gmail.com> wrote:
>>
>> Sage calculus
>> f = alg expr
But what does "f = alg expr" mean? Do you mean using predefined
single-character variables?
David
I mean this (which already works in SAGE):
sage: R.<x,y> = ZZ[x,y]; # would be x,y=vars('x,y'), which may or may
not be predefined.
sage: f = sin(x)*cos(x+y+2)
By algebraic expression I mean anything built up from certain
primitives using +,-,/,*,^, and maybe more (e.g., integral,
derivative, etc., I'm not sure). The structure for this is
already implemented in the sage/functions directory.
william
On Dec 6, 2006, at 5:03 PM, William Stein wrote:
> Sage calculus
> f = alg expr
>
> f.subs(var, val, ...)
> f.subs(dict)
> f.subs(list of pairs)
> implement recursively, with base case functions of 1 var and vars and
> constants being clear.
I would vote for f.subs(var=val, ...) as well.
> f.function(*args) - returns a callable version of f, which otherwise
> works in same way. Output is result of subs.
> this just another formal function, but with a call method.
> Also, function((vars...),expr) makes an evaluatable function.
The motivation for not providing a call function to begin with is
that the arguments have not been specified yet? I still think f(x,y)
= sin(x)*cos(x+y+3) is the most "natural" syntax, but alas it
requires the preprocessor.
> f.derivative(var) - we completely implement.
Even if we implement this (which should be relatively easy), should
we pass the results to maxima to try and simplify it? On that note,
should we have a f.simplify(), etc. method?
If we wanted, we could always add that later on top of what I proposed.
It would just be:
f = (sin(x)*cos(x+y+3)).function(x,y)
or
dummy = sin(x*) * cos(x+y+3)
f = dummy.function(x,y)
Either might be doable with the preprocessor, though I shudder...
Also, with my proposal one could also already type
f = function( (x,y), sin(x)*cos(x+y+3) )
which is nice since in Mathematica one types "f = Function[ {x,y},
Sin[x]*Cos[x+y+3] ]".
Here this would be implemented via:
def function( vars, expr):
return expr.function(*vars)
>> f.derivative(var) - we completely implement.
>
> Even if we implement this (which should be relatively easy), should
> we pass the results to maxima to try and simplify it? On that note,
> should we have a f.simplify(), etc. method?
Yes. Indeed, we should definitely have
f.simplify(numerous options) -- feed exp that defines f to maxima (or
maple or mathematica),
run various simplify commands, then parse the result.
Note that Maxima has dozens (?) of variants of simply and expand commands
with all
kinds of funny names, which is confusing, and which I hope to remedy with
SAGE.
William
We should definitely have a way of simplifying an algebraic
expression. Also, we should be able to expand a simplified expression.
And we also will want to have a method that tries to isolate a
variable. These should all be doable via Maxima.
> > f.integral(var, optional endpoints) - feed expr to maxima (or maple or
> > mathematica or mathomatic or yaccas or??) and let it compute integral
> > symbolically. Sage_eval the result (if possible - if that fails,
> > maybe wrap the external object formally).
> >
> > Basic functions: all functions like sin, cos, exp, special funcs,
> > etc, will be defined as formal functions - a lot of this is already
> > done.
> >
--
Bobby Moretti
mor...@u.washington.edu
I think either are very doable via the preprocessor, but we can hold
off for now.
>
> Also, with my proposal one could also already type
>
> f = function( (x,y), sin(x)*cos(x+y+3) )
>
> which is nice since in Mathematica one types "f = Function[ {x,y},
> Sin[x]*Cos[x+y+3] ]".
> Here this would be implemented via:
>
> def function( vars, expr):
> return expr.function(*vars)
I do think this is the cleanest pure python way of doing things.
>
>
>>> f.derivative(var) - we completely implement.
>>
>> Even if we implement this (which should be relatively easy), should
>> we pass the results to maxima to try and simplify it? On that note,
>> should we have a f.simplify(), etc. method?
>
> Yes. Indeed, we should definitely have
>
> f.simplify(numerous options) -- feed exp that defines f to maxima
> (or
> maple or mathematica),
> run various simplify commands, then parse the result.
>
> Note that Maxima has dozens (?) of variants of simply and expand
> commands
> with all
> kinds of funny names, which is confusing, and which I hope to
> remedy with
> SAGE.
>
> William
Yes, lots of at-the-fingertips documentation on the many different
versions of simplify will put us head and shoulders above every other
CAS in that regard.
This would give me extra joy. All the rest seems charming.
--
Joel
>> If we wanted, we could always add that later on top of what I
>> proposed.
>> It would just be:
>>
>> f = (sin(x)*cos(x+y+3)).function(x,y)
>>
>> or
>>
>> dummy = sin(x*) * cos(x+y+3)
>> f = dummy.function(x,y)
>>
>> Either might be doable with the preprocessor, though I shudder...
> I think either are very doable via the preprocessor, but we can hold
> off for now.
For fun, I'll think a little about that for a second, since it will
be good for Bobby to put how this would work in the SEP.
For example, we want to transform
f(x,y) = sin(x)*cos(x+y+3)
into
f = (sin(x)*cos(x+y+3)).function(x,y)
Possible logic to do this. If a statement (i.e., between ;'s
or newlines) contains an equal sign and there is an open
parenthesis to the left of the equals since, do this
transformation:
X(y) = z
gets replaced by
X = z.function(y)
where here X, y, and z are (nearly) arbitrary strings.
I think this is reasonable since in Python "if a statement (i.e.,
between ;'s or newlines) contains an equal sign and there is an open
parenthesis to the left of the equals sign", then is a *syntax error*.
We could possible also do
var(y); X=z.function(y)
where var(y) would define all formal indeterminates defined by the
string y and inject them into the interpreter's scope.
- William
>> If we wanted, we could always add that later on top of what I
>> proposed.
>> It would just be:
>>
>> f = (sin(x)*cos(x+y+3)).function(x,y)
>>
>> or
>>
>> dummy = sin(x*) * cos(x+y+3)
>> f = dummy.function(x,y)
>>
>> Either might be doable with the preprocessor, though I shudder...
> I think either are very doable via the preprocessor, but we can hold
> off for now.
For fun, I'll think a little about that. We want to transform
f(x,y) = sin(x)*cos(x+y+3)
into
f = (sin(x)*cos(x+y+3)).function(x,y)
Possible logic to do this. If a statement (i.e., between ;'s
or newlines) contains an equal sign and there is an open
parenthesis to the left of the equals since, do this
transformation:
X(y) = z
gets replaced by
X = z.function(y)
where here X, y, and z are (nearly) arbitrary strings.
I think this is reasonable since in Python "if a statement (i.e.,
between ;'s or newlines) contains an equal sign and there is an open
parenthesis to the left of the equals sign", then is a syntax error.
William
This is exactly what I was thinking. s/([^;\n]+)\s*(\([^;\n()]\))\s*=
\s*([^;\n])/\1 = (\3).function(\2)/g
> I think this is reasonable since in Python "if a statement (i.e.,
> between ;'s or newlines) contains an equal sign and there is an open
> parenthesis to the left of the equals sign", then is a *syntax error*.
Yes, this is one of the reasons I suggested it.
> We could possible also do
>
> var(y); X=z.function(y)
>
> where var(y) would define all formal indeterminates defined by the
> string y and inject them into the interpreter's scope.
>
> - William
I had actually thought about this too. I like how it makes arbitrary
(as-yet undefined) variables available, and gives access to variables
names that may contain non-indeterminate values in the current scope,
but on the other hand it overwrites anything currently defined. I
don't know python well enough to know if one can create a mini one-
line local scope.
- Robert
I don't want this to be too controversial, but in my experience, the
only syntax that students find "really easy" is a syntax based on what
appears in textbooks or what they have learned to write by hand.
Obviously 2D math notation is somewhat problematic in a linear input
syntax, but a "natural" linearisation based on a couple of
generalizable rules is much easier to handle for non-programmers than
the usual commandname(argument list) or object.methodname(argument
list) syntax. Granted, this programming style syntax has many other
advantages, and such access to calculus functionality has to be
developed as well, but I wouldn't expect newcomers to consider it
"insanely easy".
The rules for simple linear syntax are: _ for subscripts, ^ for
superscripts and / for vertical fractions, with longer arguments in
whatever brackets you like. (It's hard to make it any easier, and hard
to resist making it more complicated.) Most students know ^ and / from
graphing calculators, so they only have to get used to _ and a
(limited) number of symbol names: sqrt, sum, prod, lim, int, del, grad,
div.
The symbols are then combined in the same order as in print, which
makes it easy to guess what the commands will be. E.g.
sage: load_calculus
sage: f(x) = x^2
sage: f'(x)
2*x
sage: int f(x)dx
1/3*x^3 + C
sage: sum_(i=1)^n i
n*(n+1)/2
sage: int 1/(x^2+1)dx
tan^-1(x) + C
sage: f(x,y)=sin(x)*cos(y)
sage: del/delx(f(x,y))
cos(x)*cos(y)
Of course this is quite different from what most CASs do, but
Scientific Notebook does something similar, and this approach avoids
the overhead and confusion of having students learn first the
handwritten form, then the CAS form, and then LaTeX (the latter for
annotating their calculations).
Since the linear syntax is handled by a preprocessor, it does not
interfere with normal Sage usage, and only works after a command such
as load_calculus. It would surely distinguish Sage as an intuitive
system that even understands standard mathematical notation. It's also
in line with Python's philosophy of using e.g. list comprehension.
There are obviously some issues to resolve regarding overlap with
Python syntax and other ambiguities (e.g. int, sum are Python
functions) but the point here is that if the aim is "insanely easy",
then the ambiguities should be resolved by considering what would be
the most likely intended meaning of an input string (which is why,
e.g., Sage itself uses a preprocessor for ^ -> **). The parsing of the
linear input language is fairly simple (see
http://www1.chapman.edu/~jipsen/asciimath.html for a somewhat more
comprehensive yet easy to parse linear input form) and would produce
output of the form that has been discussed in this thread.
I think this is feasible and would make (part of) Sage easier to use
for school and undergrad math.
Cheers,
Peter