Francois Maltey (FM) and Bill Page (BP) wrote:
  How can I persuade FriCAS to write out
fricas
(1) -> ex1:=(2*log(x)+3*exp(y))*(4*sin(z)+2*log(x))
Type: Expression(Integer)
as a "sum of products"? E.g.
fricas
)set output algebra on
ex2:=box(8*log(x)*sin(z))+box(4*log(x)^2)+box(12*exp(y)*sin(z))+box(6*exp(y)*log(x))
                              y                 2       y
   (2)  8 log(x)sin(z) + 12 %e sin(z) + 4 log(x)  + 6 %e log(x)
Type: Expression(Integer)
fricas
)set output algebra off
In FriCAS, without box both of these expressions are rendered the same!
On Tuesday, September 20, 2005 8:20 AM Martin Rubey wrote:
For example:
fricas
subst(ex1, kernels ex1, [x1,x2,x3])::DMP([x1,x2,x3], INT)
Type: DistributedMultivariatePolynomial
?([x1,
x2,
x3],
Integer)
 
FM:
  Can I substitute theses elementary functions [kernels] to new variables, make
  transforms over polynoms,
yes...
FM:
  and substitute the variables back ?
Well, as soon as you go back, you'll loose the transformations you did...
The "deeper" reason why there is no domain DistributedExpression is probably
that DMP defined in gdpoly.spad asks for a List Symbol as variables. It
probably could be in fact any finite OrderedSet, but it would need some work
to get it done:
fricas
List Kernel Expression Integer has OrderedSet
Type: Boolean
A simple workaround is:
fricas
out(p, kl, vl) == 
  if reductum p = 0 
  then (eval(leadingMonomial(p)::EXPR INT, vl, kl))::OUTFORM
  else (eval(leadingMonomial(p)::EXPR INT, vl, kl))::OUTFORM _
       + out(reductum p, kl, vl)
Type: Void
fricas
output ex == 
  kl := kernels ex
  vl := [subscript('x, [i::OutputForm]) for i in 1..#kl]
  out(subst(ex, kl, vl)::DMP(vl, INT), kl, vl)
Type: Void
fricas
output(ex1)
   Cannot compile conversion for types involving local variables. In 
      particular, could not compile the expression involving :: DMP(vl,
      INT) 
   FriCAS will attempt to step through and interpret the code.
fricas
Compiling function out with type (DistributedMultivariatePolynomial(
      [x[1],x[2],x[3]],Integer), List(Kernel(Expression(Integer))), 
      List(Symbol)) -> OutputForm 
Note that this returns an element of OUTFORM. This can be circumvented:
highly undebugged, undocumented and all the bad things :-)
spad
)abb domain DEXPR DistributedExpression
DistributedExpression(R: Join(Ring, OrderedSet)): Exports == Implementation where
  EXPRR ==> Expression R
  AN    ==> AlgebraicNumber
  SUP   ==> SparseUnivariatePolynomial
  Exports == FunctionSpace R with
    if R has IntegralDomain then
      AlgebraicallyClosedFunctionSpace R
      TranscendentalFunctionCategory
      CombinatorialOpsCategory
      LiouvillianFunctionCategory
      SpecialFunctionCategory
      reduce: % -> %
        ++ reduce(f) simplifies all the unreduced algebraic quantities
        ++ present in f by applying their defining relations.
      number?: % -> Boolean
        ++ number?(f) tests if f is rational
      simplifyPower: (%,Integer) -> %
        ++ simplifyPower?(f,n) \undocumented{}
      if R has GcdDomain then
        factorPolynomial : SUP  % -> Factored SUP %
           ++ factorPolynomial(p) \undocumented{}
        squareFreePolynomial : SUP % -> Factored SUP %
           ++ squareFreePolynomial(p) \undocumented{}
      if R has RetractableTo Integer then RetractableTo AN
    coerce: EXPRR -> %
  Implementation == EXPRR add
    Rep := EXPRR
    out: (Polynomial R, List %, List %) -> OutputForm 
-- coerces the polynomial to OutputForm completely expanded and replaces the
-- variables in vl with the kernels in kl
    out(p, kl, vl) == 
      ex := leadingMonomial(p)::%
      if reductum p = 0 
      then coerce(eval(ex, vl, kl))$Rep
      else coerce(eval(ex, vl, kl))$Rep _
           + out(reductum p, kl, vl)
    coerce(ex:%):OutputForm == 
      kl := kernels ex
      vl: List % := [subscript('x, [i::OutputForm])::Symbol::% for i in 1..#kl]
      ex1: % := subst(ex, kl, vl)$%
      kl1 := map(coerce(#1)$%, kl)$ListFunctions2(Kernel %, %)
      if R has IntegralDomain then
        if denominator ex1 = 1 then
          out(retract(numerator ex1)@Polynomial(R), kl1, vl)
        else
          out(retract(numerator ex1)@Polynomial(R), kl1, vl)
            / out(retract(denominator ex1)@Polynomial(R), kl1, vl)
      else
        out(retract(ex1)@Polynomial(R), kl1, vl)
    coerce(p:EXPRR):% == p
spad
   Compiling FriCAS source code from file 
      /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/4397718924680446687-25px007.spad
      using old system compiler.
   DEXPR abbreviates domain DistributedExpression 
------------------------------------------------------------------------
   initializing NRLIB DEXPR for DistributedExpression 
   compiling into NRLIB DEXPR 
****** Domain: R already in scope
   compiling local out : (Polynomial R,List %,List %) -> OutputForm
Time: 0.03 SEC.
   compiling exported coerce : % -> OutputForm
****** Domain: R already in scope
augmenting R: (IntegralDomain)
Time: 0.01 SEC.
   compiling exported coerce : Expression R -> %
      DEXPR;coerce;E%;3 is replaced by p 
Time: 0 SEC.
****** Domain: % already in scope
augmenting %: (RetractableTo (Integer))
****** Domain: R already in scope
augmenting R: (IntegralDomain)
****** Domain: R already in scope
augmenting R: (GcdDomain)
****** Domain: R already in scope
augmenting R: (IntegralDomain)
****** Domain: R already in scope
augmenting R: (RetractableTo (Integer))
****** Domain: R already in scope
augmenting R: (LinearlyExplicitOver (Integer))
****** Domain: % already in scope
augmenting %: (RetractableTo (Integer))
****** Domain: R already in scope
augmenting R: (CharacteristicNonZero)
****** Domain: R already in scope
augmenting R: (CommutativeRing)
****** Domain: R already in scope
augmenting R: (ConvertibleTo (InputForm))
****** Domain: R already in scope
augmenting R: (ConvertibleTo (Pattern (Float)))
****** Domain: R already in scope
augmenting R: (ConvertibleTo (Pattern (Integer)))
****** Domain: R already in scope
augmenting R: (Group)
****** Domain: R already in scope
augmenting R: (IntegralDomain)
****** Domain: R already in scope
augmenting R: (PatternMatchable (Float))
****** Domain: R already in scope
augmenting R: (PatternMatchable (Integer))
****** Domain: R already in scope
augmenting R: (RetractableTo (Integer))
(time taken in buildFunctor:  74356)
;;;     ***       |DistributedExpression| REDEFINED
;;;     ***       |DistributedExpression| REDEFINED
Time: 0.12 SEC.
   Warnings: 
      [1] coerce:  $$ has no value
   Cumulative Statistics for Constructor DistributedExpression
      Time: 0.16 seconds
--------------non extending category----------------------
.. DistributedExpression(#1) of cat 
(|Join| (|FunctionSpace| |#1|)
        (CATEGORY |domain|
         (IF (|has| |#1| (|IntegralDomain|))
             (PROGN
              (ATTRIBUTE (|AlgebraicallyClosedFunctionSpace| |#1|))
              (ATTRIBUTE (|TranscendentalFunctionCategory|))
              (ATTRIBUTE (|CombinatorialOpsCategory|))
              (ATTRIBUTE (|LiouvillianFunctionCategory|))
              (ATTRIBUTE (|SpecialFunctionCategory|))
              (SIGNATURE |reduce| (% %))
              (SIGNATURE |number?| ((|Boolean|) %))
              (SIGNATURE |simplifyPower| (% % (|Integer|)))
              (IF (|has| |#1| (|GcdDomain|))
                  (PROGN
                   (SIGNATURE |factorPolynomial|
                    ((|Factored| (|SparseUnivariatePolynomial| %))
                     (|SparseUnivariatePolynomial| %)))
                   (SIGNATURE |squareFreePolynomial|
                    ((|Factored| (|SparseUnivariatePolynomial| %))
                     (|SparseUnivariatePolynomial| %))))
                  |noBranch|)
              (IF (|has| |#1| (|RetractableTo| (|Integer|)))
                  (ATTRIBUTE (|RetractableTo| (|AlgebraicNumber|)))
                  |noBranch|))
             |noBranch|)
         (SIGNATURE |coerce| (% (|Expression| |#1|)))))   has no 
(IF (|has| |#1| (|IntegralDomain|))
    (PROGN
     (ATTRIBUTE (|AlgebraicallyClosedFunctionSpace| |#1|))
     (ATTRIBUTE (|TranscendentalFunctionCategory|))
     (ATTRIBUTE (|CombinatorialOpsCategory|))
     (ATTRIBUTE (|LiouvillianFunctionCategory|))
     (ATTRIBUTE (|SpecialFunctionCategory|))
     (SIGNATURE |reduce| (% %))
     (SIGNATURE |number?| ((|Boolean|) %))
     (IF (|has| |#1| (|PolynomialFactorizationExplicit|))
         (ATTRIBUTE (|PolynomialFactorizationExplicit|))
         |noBranch|)
     (SIGNATURE |setSimplifyDenomsFlag| ((|Boolean|) (|Boolean|)))
     (SIGNATURE |getSimplifyDenomsFlag| ((|Boolean|))))
    |noBranch|)    finalizing NRLIB DEXPR 
   Processing DistributedExpression for Browser database:
--->-->DistributedExpression(constructor): Not documented!!!!
--------(reduce (% %))---------
--------(number? ((Boolean) %))---------
--------(simplifyPower (% % (Integer)))---------
--->-->DistributedExpression((simplifyPower (% % (Integer)))): Improper first word in comments: simplifyPower?
"simplifyPower?(\\spad{f},{}\\spad{n}) \\undocumented{}"
--------(factorPolynomial ((Factored (SparseUnivariatePolynomial %)) (SparseUnivariatePolynomial %)))---------
--------(squareFreePolynomial ((Factored (SparseUnivariatePolynomial %)) (SparseUnivariatePolynomial %)))---------
--->-->DistributedExpression((coerce (% (Expression R)))): Not documented!!!!
--->-->DistributedExpression(): Missing Description
; compiling file "/var/aw/var/LatexWiki/DEXPR.NRLIB/DEXPR.lsp" (written 15 MAR 2025 09:44:12 AM):
; wrote /var/aw/var/LatexWiki/DEXPR.NRLIB/DEXPR.fasl
; compilation finished in 0:00:00.020
------------------------------------------------------------------------
   DistributedExpression is now explicitly exposed in frame initial 
   DistributedExpression will be automatically loaded when needed from 
      /var/aw/var/LatexWiki/DEXPR.NRLIB/DEXPR 
Unfortunately, it seems that it is not possible to tell FriCAS to take all the exported functions of a given domain and export them. So we have to include the whole Exports section of EXPR...
fricas
ex1::DistributedExpression(Integer)
fricas
((1+2*a+3*b)*(4*c+5*d))::DEXPR INT
fricas
%::POLY INT
Type: Polynomial(Integer)
Unfortunately, it seems that it is not possible to tell Axiom to
take all the exported functions of a given domain and export them.
Isn't this a case where one should define a category relevant to
both Expression and DistributedExpression in order to avoid
duplication of the list of exports?
Yes, but since Spad doesn't support Aldor's keyword 
extend, this cannot be done post factum...