axiom-math
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Axiom-math] if-expression and variables


From: William Sit
Subject: Re: [Axiom-math] if-expression and variables
Date: Tue, 03 May 2011 03:04:34 -0400

Dear Bill:

You are right. I should not have declare "It is not possible" (even with a qualifier) since one can program around the difficulties. However, what you did essentially defines two different piecewise function, one for numeric and one for symbolic, by using "interpret" and "expr". If you use "interpret test1(y)" you would still get the wrong answer,, and similarly, if you use "expr test1(3)", then you would not have the result evaluated. Of course, you can combine the two cases and again distinguish them by testing if the input is a symbolic expression or numeric (keeping it unevaluated in the first case, and evaluating in the second).

Your routine sub is, I believe, not full proof. If x were modified inside f, would a static substitution of all occurrences of x by y work? (isn't y bound and x is not?). Or if there were a local variable x that temporarily hides the scope of the outer x. By using f:InputForm, the dummy argument for f is no longer a dummy; as a function, f is independent of the literal used for its argument. Of course, we can identify the argument of f in the sub routine without passing it as an argument for sub.

I am sure that in lisp, you can do anything. (Tim: would you rise up to the challenge?) I believe Stefan's question is whether it can be done "intuitively" (even though he did not say so explicitly). Mathematica is able to provide that, because neither the input nor the output is restricted by its type. In Axiom, maybe we can do the same with a Union like Union(Integer, InputForm).

I did not test the above claims. Axiom may surprise me.

William


On Mon, 2 May 2011 23:57:34 -0400
 Bill Page <address@hidden> wrote:
William,

On Mon, May 2, 2011 at 9:07 PM, you wrote to Stefan:
...
So the answer to your question "How is it possible ..." is, "It is not possible, in the context of piecewise functions." because no matter what the system does, you gain no new information other than what you inputted,
until you let the system know what y is, numerically.


I think we should be careful not to give the wrong impression about the capabilities of Axiom. It is not quite accurate to say that what Stefan wants to do is "impossible" in Axiom since Axiom does contain some rather sophisticated ways of representing symbolic expressions. I think it may be correct to claim that at the present time the Axiom library is fundamentally "algebraic" in orientation and not "symbolic" but the dividing line between these two views of computer algebra is
not so clear cut.

In particular, Axiom's InputForm domain represents "algebraically" everything that can be evaluated in Axiom in purely symbolic form. Normally this is only an intermediate representation which is immediately evaluated by Axiom. But with the help of a simple symbol substitution routine like the following we can do a lot more in a
purely symbolic manner.

(1) -> sub(f:InputForm, x:Symbol, y:InputForm):InputForm == ( _ atom? f => (symbol? f => (symbol f = x => y;f);f); _
            [sub(g,x,y) for g in destruct f]::InputForm)

Function declaration sub : (InputForm,Symbol,InputForm) -> InputForm
     has been added to workspace.
Type: Void

(2) -> sub

  (2)
  sub (f,x,y) ==
    if atom?(f)
      then
        if symbol?(f)
          then
            if symbol(f)= x
              then y
              else f
          else f
else ([[sub(g,x,y) for g in destruct(f)]]) :: InputForm

Type: FunctionCalled(sub)

The function 'sub' operates on symbolic "input form" f by replacing symbol x with input form y wherever x occurs. I think it should be fairly obvious how this recursive routine works except perhaps for 'destruct' which breaks a top-level input form into a list of lower-level input forms. In this way the routine traverses the entire
tree structure representing the given input form.

Now the function that Stefan has in mind can be written in a fairly
transparent manner.

(3) -> ex:InputForm := parse("if x<10 then 2*x else 5*x^2"); expr ex

  (3)
  if x < 10
    then 2x
           2
    else 5x
Type: OutputForm

The function 'parse' returns an unevaluated input form for the expression inside "...". The function 'expr' prints this in a readable manner. (InputForm is displayed in this form by default in OpenAxiom.)

(4) -> test1(x0)==sub(ex, x,x0)
Type: Void

In the definition of 'test1' the function 'sub' replaces the symbol x with the input form of x0. The result remains unevaluated.

(5) -> expr test1(y)
Compiling function sub with type (InputForm,InputForm,InputForm) ->
     InputForm
Compiling function test1 with type Variable(y) -> InputForm

  (5)
  if y < 10
    then 2y
           2
    else 5y
Type: OutputForm

But this need not always be the case.

(6) -> interpret test1(3)
Compiling function test1 with type PositiveInteger -> InputForm

  (6)  6
Type: PositiveInteger
(7) -> interpret test1(13)

  (7)  845
Type: PositiveInteger

The function 'interpret' evaluates an input form. This is possible only because in the above two instances x is replaced with a numeric value. But in general the argument to test1 need not be numeric and we can keep the unevaluated symbolic form. For example we can write:

(8) -> expr test1(x+1)
Compiling function test1 with type Polynomial(Integer) -> InputForm

  (8)
  if x + 1 < 10
    then 2(x + 1)
                 2
    else 5(x + 1)
Type: OutputForm

Perhaps this is not nearly as obvious as the way it might be done in Mathematica or Maple - especially for someone just beginning to use Axiom but I think it is equivalent to what is done in these other systems and it is fair to say that it is in keeping with the view in
Axiom that everything is fundamentally algebraic.

Regards,
Bill Page.

...

On Sat, 30 Apr 2011 20:40:28 +0200
 Stefan Karrmann <address@hidden> wrote:

Dear all,

I'm new to axiom and have a problem with piecewise functions.

test1 (x | x < 10) == 2*x
test1 (x | x < 10) == 5*x^2
test1
->   test1 (x | x < 10) == 2x
 test1 (x | ^ x < 10) == 5x
                                                 Type: FunctionCalled
test1 y
->
   2
 5y

I expected something like (if y < 10 then 2*y else 5*y**2).

How is it possible to pass a Variable to a piecewise function respecting
the pieces?

PS: Using a block and => or explicit if-then-else does not help.

--
Kind regards,
Stefan


William Sit, Professor Emeritus
Mathematics, City College of New York
Office: R6/291D Tel: 212-650-5179
Home Page: http://scisun.sci.ccny.cuny.edu/~wyscc/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]