I've been reading this thread. It seems to me that what people are seeking
is a symbolic algebra rather than a computer algebra system. The distinction
is that a symbolic system manipulates input as parse trees in syntactic form.
A computer algebra system manipulates input as semantic forms. It appears
that you want to recover the syntax from the semantics, a very hard problem.

This discussion came up before. At the time I wrote the beginnings of a
symbolic front end to Axiom based on Joel Cohen's work. Joel has given
me permission to use his books as part of the effort.

Joel describes a symbolic, expression tree based system for doing
computational mathematics. I call this a "Cohen Algebra". Using these
expression trees allows us to carefully craft and manipulate the expressions
in ways that Axiom would not normally permit because they are not
semantically valid. As long as the forms are never coerced to Axiom
domains until they are semantically valid, it is possible to do many
"badly formed" intermediate manipulations, some of which are very
useful for teaching purposes.

We can get the Cohen algebra into Axiom using categories, domains, and
packages that support expression tree I/O and coercions to and from
Axiom domains, e.g.
  cohenPolynomial(cohenInteger) <-> Polynomial(Integer)

This enables us to address several issues that have been outstanding
in the field for a while, including those mentioned at the last conference:

 *) It would be possible to do "step-by-step" output (Watt?)
         That is, you could show the steps of solving 3*x=6
          by showing the step of dividing both sides by 3
             3       6
             -  x =  -
             3       3
        and preserve the 3 on both sides

  *) It would be possible to do "step-by-step* explanations (Watt?)
         Algorithms in the Cohen domains could easily have
         explanations attached to the operations so that it could
         automatically print:
              "divide each side by 3"

    *) It would be possible to modify the output if the result
         turned into "wallpaper" (as mentioned by Davenport).
         So you could simply print the condensed output of a
         groebner basis computation.

     *) It would be much easier to input and output forms for
         other systems (e.g. supporting OpenMath output)
         (Davenport)

I plan to do more work on Cohen domains because all of the
above features would be useful. My simple test example domains
are attached.

In my opinion, the idea of using InputForm beyond its intended
interpreter connections is not a viable effort. It would be much
easier and more profitable to construct something like the Cohen
domains to support the goal.

Tim

============================================

)abbrev category CCAT CohenCategory

+++ Author: Timothy Daly
+++ Date Created: 7 April 2007
+++ Description: Joel Cohen's Computer Algebra and Symbolic Computation
CohenCategory(): Category == SetCategory with

 kind:(CExpr)->Boolean
   ++ kind(CExpr)
 operand:(CExpr,Integer)->CExpr
   ++ operand:(CExpr,Integer)
 numberOfOperand:(CExpr)->Integer
   ++ numberOfOperand:(CExpr)->Integer
 construct:(CExpr,CExpr)->CExpr
   ++ construct:(CExpr,CExpr)->CExpr

-------------------------------------------------------------------
)abbrev domain CTERM CohenTerm

+++ Author: Timothy Daly
+++ Date Created: 7 April 2007
+++ Description: Joel Cohen's Computer Algebra and Symbolic Computation
CohenTerm(): Exports == Implementation where
 OUT     ==> OutputForm
 ATTRIBS ==> Record(attrib: String, value: String)
 UNION   ==> Union(Symbol,String,Integer)
 TAGS    ==> Record(name:UNION, tags:List ATTRIBS)

 Exports ==> CohenCategory with
   term: () -> %
   term: Symbol -> %
   term: String -> %
   term: Integer -> %
   name: % -> String
   tags: % -> List ATTRIBS
   coerce: Symbol -> %
   coerce: String -> %
   coerce: Integer -> %
   coerce: % -> OUT
   _=: (%,%) -> Boolean

 Implementation ==> add

   Rep := TAGS

   tagPair(atype:String,thetype:String):ATTRIBS ==
     attr:ATTRIBS:=[atype,thetype]

   name(t0:%):String ==
     t1:=t0.name
     t1 case Symbol  => string t1
     t1 case String  => t1
     t1 case Integer => string t1
     "failed"

   tags(t0:%):List ATTRIBS == t0.tags

   term():% ==
     attr:List ATTRIBS:= list tagPair("type","String")
     aname:=""::UNION
     result:TAGS:=[aname,attr]
     result

   term(s:Symbol):%  == [s,[tagPair("type","Symbol")]]
   coerce(s:Symbol):%  == [s,[tagPair("type","Symbol")]]

   term(s:String):%  == [s,[tagPair("type","String")]]
   coerce(s:String):%  == [s,[tagPair("type","String")]]

   term(s:Integer):% == [s,[tagPair("type","Integer")]]
   coerce(s:Integer):% == [s,[tagPair("type","Integer")]]

   coerce(arg:%):OUT ==
     t0:=arg.name
     t1:=arg.tags
     t2:=
       t0 case Symbol  => outputForm t0
       t0 case String  => outputForm t0
       t0 case Integer => outputForm t0
       "failed"
     --bracket [ t2, t1.1 ]
     t2

   a = b ==
     a.name = b.name


-------------------------------------------------------------------
)abbrev domain CTREE CohenTree

+++ Author: Timothy Daly
+++ Date Created: 7 April 2007
+++ Description: Joel Cohen's Computer Algebra and Symbolic Computation
CohenTree(S: CohenCategory): Exports == Implementation where
 Exports == BinaryTreeCategory(S) with
  cohenTree: S -> %
   ++ cohenTree(v) is an non-empty cohen tree
   ++ with value v, and left and right empty.
   ++
   ++X t1:=cohenTree([1,2,3])
cohenTree: (%,S,%) -> % ++ cohenTree(l,v,r) creates a cohen tree with
   ++ value v with left subtree l and right subtree r.
   ++
   ++X t1:=cohenTree([1,2,3])
   ++X t2:=cohenTree([4,5,6])
   ++X cohenTree(t1,[7,8,9],t2)

  cohenTree: (%,S) -> %
   ++ cohenTree(v,r) creates a cohen tree with
   ++ value v with right subtree r.

  cohenTree: (S,%) -> %
   ++ cohenTree(l,v) creates a cohen tree with
   ++ value v with left subtree l

  empty: () -> %
   ++ empty()
  empty?: % -> Boolean
   ++ empty?(a)
  leaf?: % -> Boolean
   ++ leaf?(a)
  left: % -> %
   ++ left(a)
  node: (%,S,%) -> %
   ++ node(a,b,c)
  right: % -> %
   ++ right(a)
  setleft_!: (%,%) -> %
   ++ setleft!(a,b)
  setright_!: (%,%) -> %
   ++ setright!(a,b)
  setvalue_!: (%,S) -> S
   ++ setvalue!(a,b)
  value: % -> S
   ++ value(a)
Implementation == add
  Rep := List Tree S

  cohenTree(v:S) == node(empty(),v,empty())
  cohenTree(l:%,v:S,r:%):% == node(l,v,r)
  cohenTree(l:%,v:S):% == node(l,v,empty())
  cohenTree(v:S,r:%):% == node(empty(),v,r)
  empty()== [] pretend %
  empty? t == empty?(t)$Rep
  leaf? t  == empty? t or empty? left t and empty? right t
  left t ==
    empty? t => error "cohenTree:no left"
    children first t
  node(l,v,r) == cons(tree(v,l:Rep),r:Rep)
  right t ==
    empty? t => error "cohenTree:no right"
    rest t
  setleft_!(t1,t2) ==
    empty? t1 => error "cohenTree:no left to set"
    setchildren_!(first(t1:Rep),t2:Rep)
    t1
  setright_!(t1,t2) ==
    empty? t1 => error "cohenTree:no right to set"
    setrest_!(t1:List Tree S,t2)
  setvalue_!(t,nd) ==
    empty? t => error "cohenTree:no value to set"
    setvalue_!(first(t:Rep),nd)
    nd
  value t ==
    empty? t => error "cohenTree:no value"
    value first t
  t1 = t2 == (t1::Rep) =$Rep (t2::Rep)


-------------------------------------------------------------------
--  a:=a::CTERM
--  b:=b::CTERM
--  c:=a+b
--  left(c)
--  right(c)
--  d:=3::CTERM
--  e:=d*c
--  left(e)
--  right(e)
--
--  -- Figure 3.4 p88
--  )clear all
--
--  c:=c::CTERM
--  d:=d::CTERM
--  x:=x::CTERM
--  two:=2::CTERM
--  e:=c+d*x^2
--
--  -- Figure 3.5a p89
--  )clear all
--  a:=a::CTERM
--  b:=b::CTERM
--  c:=c::CTERM
--  d:=a*b+c
--  e:=-d

-------------------------------------------------------------------
)abbrev package CMATH CohenMath

+++ Author: Timothy Daly
+++ Date Created: 7 April 2007
+++ Description: Joel Cohen's Computer Algebra and Symbolic Computation
CohenMath: Exports == Implementation where
 TERM ==> CohenTerm
 TREE ==> CohenTree(TERM)

 Exports ==> with
  _-: (TERM) -> TREE
   ++ -a
  _-: (TREE) -> TREE
   ++ -a

--   "!": (TERM) -> TREE
--    ++ a!
--   "!": (TREE) -> TREE
--    ++ a!

  _-: (TERM,TERM) -> TREE
   ++ a-b
  _-: (TERM,TREE) -> TREE
   ++ a-b
  _-: (TREE,TERM) -> TREE
   ++ a-b
  _-: (TREE,TREE) -> TREE
   ++ a-b

  _+: (TERM,TERM) -> TREE
   ++ a+b
  _+: (TERM,TREE) -> TREE
   ++ a+b
  _+: (TREE,TERM) -> TREE
   ++ a+b
  _+: (TREE,TREE) -> TREE
   ++ a+b

  _*: (TERM,TERM) -> TREE
   ++ a*b
  _*: (TERM,TREE) -> TREE
   ++ a*b
  _*: (TREE,TERM) -> TREE
   ++ a*b
  _*: (TREE,TREE) -> TREE
   ++ a*b

  _^: (TERM,TERM) -> TREE
   ++ a*b
  _^: (TERM,TREE) -> TREE
   ++ a*b
  _^: (TREE,TERM) -> TREE
   ++ a*b
  _^: (TREE,TREE) -> TREE
   ++ a*b

 Implementation ==> add

  --- handle unary prefix terms

  prefixTerm(op:TERM,b:TERM):TREE  == cohenTree(op,cohenTree(b))
  prefixTree(op:TERM,b:TREE):TREE  == cohenTree(op,b)

  --- handle unary postfix terms

  postfixTerm(a:TERM,op:TERM):TREE == cohenTree(cohenTree(a),op)
  postfixTree(a:TREE,op:TERM):TREE == cohenTree(a,op)

  --- handle binary terms

  termOpTerm(a:TERM,op:TERM,b:TERM):TREE ==
     cohenTree(cohenTree(a),op,cohenTree(b))

  termOpTree(a:TERM,op:TERM,b:TREE):TREE ==
     cohenTree(cohenTree(a),op,b)

  treeOpTerm(a:TREE,op:TERM,b:TERM):TREE ==
     cohenTree(a,op,cohenTree(b))

  treeOpTree(a:TREE,op:TERM,b:TREE):TREE ==
     cohenTree(a,op,b)

  _-(b:TERM):TREE         == prefixTerm(term("-")$TERM,b)
  _-(c:TREE):TREE         == prefixTree(term("-")$TERM,c)

--   "!"(a:TERM):TREE         == postfixTerm(a,term("!")$TERM)
--   "!"(a:TREE):TREE         == postfixTree(a,term("!")$TERM)

  _-(a:TERM, b:TERM):TREE == termOpTerm(a,term("-")$TERM,b)
  _-(a:TERM, b:TREE):TREE == termOpTree(a,term("-")$TERM,b)
  _-(a:TREE, b:TERM):TREE == treeOpTerm(a,term("-")$TERM,b)
  _-(a:TREE, b:TREE):TREE == treeOpTree(a,term("-")$TERM,b)

  _+(a:TERM, b:TERM):TREE == termOpTerm(a,term("+")$TERM,b)
  _+(a:TERM, b:TREE):TREE == termOpTree(a,term("+")$TERM,b)
  _+(a:TREE, b:TERM):TREE == treeOpTerm(a,term("+")$TERM,b)
  _+(a:TREE, b:TREE):TREE == treeOpTree(a,term("+")$TERM,b)

  _*(a:TERM, b:TERM):TREE == termOpTerm(a,term("*")$TERM,b)
  _*(a:TERM, b:TREE):TREE == termOpTree(a,term("*")$TERM,b)
  _*(a:TREE, b:TERM):TREE == treeOpTerm(a,term("*")$TERM,b)
  _*(a:TREE, b:TREE):TREE == treeOpTree(a,term("*")$TERM,b)

  _^(a:TERM, b:TERM):TREE == termOpTerm(a,term("^")$TERM,b)
  _^(a:TERM, b:TREE):TREE == termOpTree(a,term("^")$TERM,b)
  _^(a:TREE, b:TERM):TREE == treeOpTerm(a,term("^")$TERM,b)
  _^(a:TREE, b:TREE):TREE == treeOpTree(a,term("^")$TERM,b)


-------------------------------------------------------------------
)abbrev domain COHEN CohenAlgebra

+++ Author: Timothy Daly (based on Joel Cohen's books)
+++ Date Created: 7 April 2007
+++ Description:
+++ This type represents symbolic algebra as detailed in Joel Cohen's
+++ books "Computer Algebra and Symbolic Computation"
+++ A.K. Peters, Ltd. ISBN 1-56881-159-4
+++
+++ Elements of this domain are purely symbolic expressions represented
+++ in a tree structure.

CohenAlgebra(X : CohenCategory) : CohenCategory with

 _+: (X,X) -> %
  ++ x + y is the formal sum of the input arguments

 _/: (X,X) -> %
  ++ x / y is the formal fraction of the input arguments

 numer : % -> X
  ++ numer(x) is the numerator of the formal fraction

 denom : % -> X
  ++ denom(x) is the denominator of the formal fraction

 if X has IntegralDomain then

   coerce : % -> Fraction(X)
    ++ coerce(x) from here to Fraction(there)

   coerce : Fraction(X) -> %
    ++ coerce(x) from Fraction(there) to here

 if X has Field then
coerce : % -> X
    ++ coerce from here to Field(there)

== add

 import Record(num : X, den : X)

 Rep := Record(num : X, den : X)  -- representation

-- (a::CTERM + b::CTERM)$COHEN(CTERM)
-- c:CTERM:=d
-- e:CTERM:=f
-- (c+e)$COHEN(CTERM)

 (n:X + d:X):% == [n,d]

-- (a::CTERM / b::CTERM)$COHEN(CTERM)
-- c:CTERM:=d
-- e:CTERM:=f
-- (c/e)$COHEN(CTERM)

 (n:X / d:X):% == [n,d]

-- g:=(c/e)$COHEN(CTERM)
-- h:=(c/e)$COHEN(CTERM)
-- (g=h)
-- (g=h)::Boolean
-- i:=(a::CTERM / b::CTERM)$COHEN(CTERM)
-- j:=(a::CTERM / b::CTERM)$COHEN(CTERM)
-- (i=j)::Boolean
-- (g=i)
-- (g=i)::Boolean

 _=(x:%, y:%):Boolean == (x.num = y.num) and (x.den = y.den)

-- numer g
-- numer i

 numer(r:%):X == r.num

--denom g
--denom i

 denom(r:%):X == r.den

 coerce(r:%):OutputForm == (r.num :: OutputForm) / (r.den :: OutputForm)



-- COMPLEX(INT) has FIELD
-- COMPLEX(INT) has IntegralDomain
-- p:COMPLEX(INT):=2
-- p::FRAC(COMPLEX(INT))::COHEN(COMPLEX(INT))

 if X has IntegralDomain then

   coerce(r : %) : Fraction(X)
     ==  (r.num / r.den) @ Fraction(X)

coerce(x : Fraction(X)) : % == x pretend %
-- FRAC(POLY(INT)) has FIELD
-- m:=(x^2)@FRAC(POLY(INT))
-- m::COHEN(POLY(INT))

 if X has Field then
   coerce(r : %) : X
     == (r.num / r.den) @ X







_______________________________________________
Axiom-developer mailing list
Axiom-developer@nongnu.org
http://lists.nongnu.org/mailman/listinfo/axiom-developer

Reply via email to