fricas
(1) -> )lib CARTEN MONAL PROP
   >> System error:
   The value
  15684
is not of type
  LIST
spad
)abbrev domain LOP LinearOperator
LinearOperator(gener:OrderedFinite,K:Field): Exports == Implementation where
  NNI ==> NonNegativeInteger
  NAT ==> PositiveInteger
  T ==> CartesianTensor(1,dim,K)
  Exports ==> Join(Ring, FramedModule K, Monoidal NNI, RetractableTo K) with
    dimension: () -> CardinalNumber
    arity: % -> Prop %
    basisOut: () -> List %
    basisIn: () -> List %
    tensor: % -> T
    I : () -> %
    map: (K->K,%) -> %
    if K has Evalable(K) then Evalable(K)
    eval: % -> %
    ravel: % -> List K
    unravel: (Prop %,List K) -> %
    coerce:(x:List NAT) -> %
      ++ identity for composition and permutations of its products
    coerce:(x:List None) -> %
      ++ [] = 1
    elt: (%,%) -> %
    elt: (%,NAT) -> %
    elt: (%,NAT,NAT) -> %
    elt: (%,NAT,NAT,NAT) -> %
    _/: (Tuple %,Tuple %) -> %
    _/: (Tuple %,%) -> %
    _/: (%,Tuple %) -> %
      ++ yet another syntax for product
    ev: NAT -> %
      ++ (2,0)-tensor for evaluation
    co: NAT -> %
      ++ (0,2)-tensor for co-evaluation
  Implementation ==> add
    import List NNI
    import NAT
    L ==> Record(domain:NNI, codomain:NNI, data:T)
    -- FreeMonoid provides unevaluated products
    Rep ==> FreeMonoid L
    RR ==> Record(gen:L,exp:NNI)
    rep(x:%):Rep == x pretend Rep
    per(x:Rep):% == x pretend %
    dim:NNI := size()$gener
    dimension():CardinalNumber == coerce dim
    -- Prop (arity)
    dom(f:%):NNI ==
      r:NNI := 0
      for y in factors(rep f) repeat
        r:=r+(y.gen.domain)*(y.exp)
      return r
    cod(f:%):NNI ==
      r:NNI := 0
      for y in factors(rep f) repeat
        r:=r+(y.gen.codomain)*(y.exp)
      return r
    prod(f:L,g:L):L ==
      r:T := product(f.data,g.data)
      -- dom(f) + cod(f) + dom(g) + cod(g)
      p:List Integer := concat                _
        [[i for i in 1..(f.domain)],              _
        [(f.domain)+(f.codomain)+i for i in 1..(g.domain)], _
        [(f.domain)+i for i in 1..(f.codomain)],        _
        [(f.domain)+(g.domain)+(f.codomain)+i for i in 1..(g.codomain)]]
        -- dom(f) + dom(g) + cod(f) + cod(g)
      --output("prod p = ",p::OutputForm)$OutputPackage
      [(f.domain)+(g.domain),(f.codomain)+(g.codomain),reindex(r,p)]
    dats(fs:List RR):L ==
      r:L := [0,0,1$T]
      for y in fs repeat
        t:L:=y.gen
        for n in 1..y.exp repeat
          r:=prod(r,t)
      return r
    dat(f:%):L == dats factors rep f
    arity(f:%):Prop % == f::Prop %
    eval(f:%):% == per coerce dat(f)
    retractIfCan(f:%):Union(K,"failed") ==
      dom(f)=0 and cod(f)=0 => retract(dat(f).data)$T
      return "failed"
    retract(f:%):K ==
      dom(f)=0 and cod(f)=0 => retract(dat(f).data)$T
      error "failed"
    -- basis
    basisOut():List % == [per coerce [0,1,entries(row(1,i)$SquareMatrix(dim,K))::T] for i in 1..dim]
    basisIn():List % == [per coerce [1,0,entries(row(1,i)$SquareMatrix(dim,K))::T] for i in 1..dim]
    ev(n:NAT):% == reduce(_+,[ dx^n * dx^n for dx in basisIn()])$List(%)
    --  dx:= basisIn()
    --  reduce(_+,[ (dx.i)^n * (dx.i)^n for i in 1..dim])
    co(n:NAT):% == reduce(_+,[ Dx^n * Dx^n for Dx in basisOut()])$List(%)
    --  Dx:= basisOut()
    --  reduce(_+,[ (Dx.i)^n * (Dx.i)^n for i in 1..dim])
    -- manipulation
    map(f:K->K, g:%):% == per coerce [dom g,cod g,unravel(map(f,ravel dat(g).data))$T]
    if K has Evalable(K) then
      eval(g:%,f:List Equation K):% == map((x:K):K+->eval(x,f),g)
    ravel(g:%):List K == ravel dat(g).data
    unravel(p:Prop %,r:List K):% ==
      dim^(dom(p)+cod(p)) ~= #r => error "failed"
      per coerce [dom(p),cod(p),unravel(r)$T]
    tensor(x:%):T == dat(x).data
    -- sum
    (f:% + g:%):% ==
      dat(f).data=0 => g
      dat(g).data=0 => f
      dom(f) ~= dom(g) or cod(f) ~= cod(g) => error "arity"
      per coerce [dom f,cod f,dat(f).data+dat(g).data]
    (f:% - g:%):% ==
      dat(f).data=0 => g
      dat(g).data=0 => f
      dom(f) ~= dom(f) or cod(g) ~= cod(g) => error "arity"
      per coerce [dom f, cod f,dat(f).data-dat(g).data]
    _-(f:%):% == per coerce [dom f, cod f,-dat(f).data]
    -- identity for sum (trivial zero map)
    0 == per coerce [0,0,0]
    zero?(f:%):Boolean == dat(f).data = 0 * dat(f).data
    -- identity for product
    1:% == per 1
    one?(f:%):Boolean == one? rep f
    -- identity for composition
    I == per coerce [1,1,kroneckerDelta()$T]
    (x:% = y:%):Boolean == rep eval x = rep eval y
    -- permutations and identities
    coerce(p:List NAT):% ==
      r:=I^#p
      #p = 1 and p.1 = 1 => return r
      p1:List Integer:=[i for i in 1..#p]
      p2:List Integer:=[#p+i for i in p]
      p3:=concat(p1,p2)
      --output("coerce p3 = ",p3::OutputForm)$OutputPackage
      per coerce [#p,#p,reindex(dat(r).data,p3)]
    coerce(p:List None):% == per coerce [0,0,1]
    coerce(x:K):% == x*1
    -- tensor product
    elt(f:%,g:%):% == f * g
    elt(f:%,g:NAT):% == f * I^g
    elt(f:%,g1:NAT,g2:NAT):% == f * [g1 @ NAT,g2 @ NAT]::List NAT::%
    elt(f:%,g1:NAT,g2:NAT,g3:NAT):% == f * [g1 @ NAT,g2 @ NAT,g3 @ NAT]::List NAT::%
    apply(f:%,g:%):% == f * g
    (f:% * g:%):% == per (rep f * rep g)
    leadI(x:Rep):NNI ==
      r:=hclf(x,rep(I)^size(x))
      size(r)=0 => 0
      nthExpon(r,1)
    trailI(x:Rep):NNI ==
      r:=hcrf(x,rep(I)^size(x))
      size(r)=0 => 0
      nthExpon(r,1)
    -- composition:
    -- f/g : A^n -> A^p = f:A^n -> A^m / g:A^m -> A^p
    (ff:% / gg:%):% ==
      g:=gg; f:=ff
      -- partial application from the left
      nn:=subtractIfCan(cod ff,dom gg)
      if nn case NNI and nn>0 then
      -- apply g on f from the left, pass extra f outputs on the right
        print(hconcat([message("arity warning: "), _
              over(arity(ff)::OutputForm, _
                   arity(gg)::OutputForm*(arity(I)::OutputForm)^nn::OutputForm) ]))$OutputForm
        g:=gg*I^nn
      mm:=subtractIfCan(dom gg, cod ff)
      --  apply g on f from the left, add extra g inputs on the left
      if mm case NNI and mm>0 then
        print(hconcat([message("arity warning: "), _
              over((arity(I)::OutputForm)^mm::OutputForm*arity(ff)::OutputForm, _
                   arity(gg)::OutputForm)]))$OutputForm
        f:=I^mm*ff
      -- parallelize composition f/g = (f1/g1)*(f2/g2)
      if cod(f)>0 then
        i:Integer:=1
        j:Integer:=1
        n:NNI:=1
        m:NNI:=1
        f1 := per coerce nthFactor(rep f,1)
        g1 := per coerce nthFactor(rep g,1)
        while cod(f1)~=dom(g1) repeat
          if cod(f1) < dom(g1) then
            if n < nthExpon(rep f,i) then
              n:=n+1
            else
              n:=1
              i:=i+1
            f1 := f1 * per coerce nthFactor(rep f,i)
          else if cod(f1) > dom(g1) then
            if m < nthExpon(rep g,j) then
              m:=m+1
            else
              n:=1
              j:=j+1
            g1 := g1 * per coerce nthFactor(rep g,j)
        f2 := per overlap(rep f1, rep f).rm
        g2 := per overlap(rep g1,rep g).rm
        f := f1
        g := g1
      else
        f2 := per 1
        g2 := per 1
      -- factor parallel identites
      nl := leadI hclf(rep f,rep g)
      nI := rep(I)^nl
      f := per overlap(nI,rep f).rm
      g := per overlap(nI,rep g).rm
      ln := trailI hcrf(rep f,rep g)
      In := rep(I)^ln
      f := per overlap(rep f,In).lm
      g := per overlap(rep g,In).lm
      -- remove leading and trailing identities
      nf := leadI rep f
      f := per overlap(rep(I)^nf,rep f).rm
      ng := leadI rep g
      g := per overlap(rep(I)^ng,rep g).rm
      fn := trailI rep f
      f := per overlap(rep f,rep(I)^fn).lm
      gn := trailI rep g
      g := per overlap(rep g,rep(I)^gn).lm
      -- Factoring out parallel identities guarantees that:
      if nf>0 and ng>0 then error "either nf or ng or both must be 0"
      if fn>0 and gn>0 then error "either fn or gn or both must be 0"
      -- Exercise for Reader:
      --   Prove the following contraction and permutation is correct by
      --   considering all 9 cases for (nf=0 or ng=0) and (fn=0 or gn=0).
      -- output("leading [nl,nf,ng] = ",[nl,nf,ng]::OutputForm)$OutputPackage
      -- output("trailing [ln,fn,gn] = ",[ln,fn,gn]::OutputForm)$OutputPackage
      r:T := contract(cod(f)-ng-gn, dat(f).data,dom(f)+ng+1, dat(g).data,nf+1)
      p:List Integer:=concat [ _
        [dom(f)+gn+i for i in 1..nf], _
        [i for i in 1..dom(f)], _
        [dom(f)+nf+ng+i for i in 1..fn], _
        [dom(f)+i for i in 1..ng], _
        [dom(f)+nf+ng+fn+gn+i for i in 1..cod(g)], _
        [dom(f)+ng+i for i in 1..gn] ]
      --print(p::OutputForm)$OutputForm
      r:=reindex(r,p)
      if f2=1 and g2=1 then
        return per nI * per coerce [nf+dom(f)+fn,ng+cod(g)+gn,r] * per In
      if f2=1 then error "g2 should be 1"
      if g2=1 then error "f2 should be 1"
      return per nI * per coerce [nf+dom(f)+fn,ng+cod(g)+gn,r] * per In * (f2/g2)
    -- another notation for composition of products
    (t:Tuple % / x:%):% == t / construct([x])$PrimitiveArray(%)::Tuple(%)
    (x:% / t:Tuple %):% == construct([x])$PrimitiveArray(%)::Tuple(%) / t
    (f:Tuple % / g:Tuple %):% ==
      fs:List % := [select(f,i) for i in 0..#(f)-1]
      gs:List % := [select(g,i) for i in 0..#(g)-1]
      fr:=reduce(elt@(%,%)->%,fs,1)
      gr:=reduce(elt@(%,%)->%,gs,1)
      fr / gr
    (x:K * y:%):% == per coerce [dom y, cod y,x*dat(y).data]
    --(x:% * y:K):% == per coerce [dom x,cod x,dat(x).data*y]
    (x:Integer * y:%):% == per coerce [dom y,cod y,x*dat(y).data]
    -- display operators using basis
    show(x:%):OutputForm ==
      dom(x)=0 and cod(x)=0 => return (dat(x).data)::OutputForm
      if size()$gener > 0 then
        gens:List OutputForm:=[index(i::PositiveInteger)$gener::OutputForm for i in 1..dim]
      else
        -- default to numeric indices
        gens:List OutputForm:=[i::OutputForm for i in 1..dim]
      -- input basis
      inps:List OutputForm := []
      for i in 1..dom(x) repeat
        empty? inps => inps:=gens
        inps:=concat [[(inps.k * gens.j) for j in 1..dim] for k in 1..#inps]
      -- output basis
      outs:List OutputForm := []
      for i in 1..cod(x) repeat
        empty? outs => outs:=gens
        outs:=concat [[(outs.k * gens.j) for j in 1..dim] for k in 1..#outs]
      -- combine input (superscripts) and/or output(subscripts) to form basis symbols
      bases:List OutputForm
      if #inps > 0 and #outs > 0 then
        bases:=concat([[ scripts(message("|"),[i,j]) for i in outs] for j in inps])
      else if #inps > 0 then
        bases:=[super(message("|"),i) for i in inps]
      else if #outs > 0 then
        bases:=[sub(message("|"),j) for j in outs]
      else
        bases:List OutputForm:= []
      -- merge bases with data to form term list
      terms:=[(k=1 => base;k::OutputForm*base)
        for base in bases for k in ravel dat(x).data | k~=0]
      empty? terms => return 0::OutputForm
      -- combine the terms
      return reduce(_+,terms)
    coerce(x:%):OutputForm ==
      r:OutputForm := empty()
      for y in factors(rep x) repeat
        if y.exp = 1 then
          if size rep x = 1 then
            r := show per coerce y.gen
          else
            r:=r*paren(list show per coerce y.gen)
        else
          r:=r*paren(list show per coerce y.gen)^(y.exp::OutputForm)
      return r
spad
   Compiling FriCAS source code from file 
      /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/5221482899668613588-25px002.spad
      using old system compiler.
   LOP abbreviates domain LinearOperator 
------------------------------------------------------------------------
   initializing NRLIB LOP for LinearOperator 
   compiling into NRLIB LOP 
****** comp fails at level 1 with expression: ******
((|Monoidal| (|NonNegativeInteger|)))
****** level 1  ******
x:= (Monoidal (NonNegativeInteger))
m:= $EmptyMode
f:=
((((K # . #1=#) (|gener| # #) (|LinearOperator| #) (K . #1#) ...)))
   >> Apparent user error:
   cannot compile (Monoidal (NonNegativeInteger)) 
Tests
fricas
L := LOP(OVAR ['1,'2],EXPR INT)
   LinearOperator is an unknown constructor and so is unavailable. Did 
      you mean to use -> but type something different instead?
Various special cases of composition
fricas
-- case 1
test( X/X = [1,2] )
   There are 3 exposed and 0 unexposed library operations named 
      equation having 2 argument(s) but none was determined to be 
      applicable. Use HyperDoc Browse, or issue
                            )display op equation
      to learn more about the available operations. Perhaps 
      package-calling the operation or using coercions on the arguments
      will allow you to apply the operation.
   Cannot find a definition or applicable library operation named 
      equation with argument type(s) 
                        Fraction(Polynomial(Integer))
                            List(PositiveInteger)
      Perhaps you should use "@" to indicate the required return type, 
      or "$" to specify which version of the function you need.