From f41b841d58ca904ed3854b5c850f3669de8f33e4 Mon Sep 17 00:00:00 2001 From: Michael Reed <18372368+chakravala@users.noreply.github.com> Date: Sat, 21 Dec 2024 18:32:23 -0500 Subject: [PATCH] refined bilinearity --- src/forms.jl | 371 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 320 insertions(+), 51 deletions(-) diff --git a/src/forms.jl b/src/forms.jl index cc6717f..44bd7f7 100644 --- a/src/forms.jl +++ b/src/forms.jl @@ -1,11 +1,13 @@ # This file is part of Grassmann.jl. It is licensed under the AGPL license # Grassmann Copyright (C) 2019 Michael Reed -export TensorNested, Projector, Dyadic, Proj, outer, operator +export TensorNested, Projector, Dyadic, Proj, outer, operator, gerschgorin export DiagonalOperator, TensorOperator, Endomorphism, Outermorphism, outermorphism -export sylvester, characteristic, eigvecs, eigvals, eigpolys, eigprods, eigmults +export sylvester, characteristic, eigen, eigvecs, eigvals, eigpolys, eigprods, eigmults +export eigvalsreal, eigvalscomplex, eigvecsreal, eigvecscomplex, eigenreal, eigencomplex export MetricTensor, metrictensor, metricextensor, InducedMetric -import LinearAlgebra: eigvals, eigvecs +export @TensorOperator, @Endomorphism, @Outermorphism, @SpectralOperator +import LinearAlgebra: eigvals, eigvecs, eigen ## conversions @@ -143,7 +145,7 @@ function (W::Submanifold{Q,M,S})(m::Multivector{V,T}) where {Q,M,V,S,T} end end -#### need separate storage for m and F for caching +# need separate storage for m and F for caching const dualform_cache = Vector{Tuple{Int,Bool}}[] const dualformC_cache = Vector{Tuple{Int,Bool}}[] @@ -372,14 +374,38 @@ struct Projector{V,T,Λ} <: TensorNested{V,T} end const Proj = Projector +const SpectralOperator{V,T<:Simplex{V},Λ} = Projector{V,T,Λ} +export SpectralOperator Proj(v::T,λ=1) where T<:TensorGraded{V} where V = Proj{V}(v/abs(v),λ) Proj(v::Chain{W,1,<:Chain{V}},λ=1) where {V,W} = Proj{V}(Chain(value(v)./abs.(value(v))),λ) #Proj(v::Chain{V,1,<:TensorNested},λ=1) where V = Proj{V}(v,λ) +SpectralOperator(t::AbstractMatrix) = SpectralOperator(Endomorphism(t)) +SpectralOperator{V}(t::AbstractMatrix) where V = SpectralOperator(Endomorphism{V}(t)) + +macro SpectralOperator(ex) + SpectralOperator(eval(ex)) +end (P::Projector)(x) = contraction(P,x) +function (T::Projector{V})(x::TensorAlgebra{V},y::TensorAlgebra{V}) where V + vecdot(contraction(T,x),y) +end + +function Base.exp(P::Proj{V}) where V + out = exp(Chain(P))[1] + Proj{V}(out/sqrt(out[1])) +end +function Base.log(P::Proj{V}) where V + out = log(Endomorphism(P))[1] + Proj{V}(out/sqrt(out[1])) +end +Base.exp(P::SpectralOperator{V}) where V = Proj{V}(P.v,map(exp,P.λ)) +Base.log(P::SpectralOperator{V}) where V = Proj{V}(P.v,map(log,P.λ)) +Base.inv(P::SpectralOperator{V}) where V = Proj{V}(P.v,map(inv,P.λ)) getindex(P::Proj,i::Int,j::Int) = P.v[i]*P.v[j] +getindex(P::Proj{V,<:Chain{W,1,<:Chain}},i::Int) where {V,W} = Proj{V}(P.v[i],P.λ[i]) getindex(P::Proj{V,<:Chain{W,1,<:Chain}} where {V,W},i::Int,j::Int) = sum(column(P.v,i).*column(P.v,j)) #getindex(P::Proj{V,<:Chain{V,1,<:TensorNested}} where V,i::Int,j::Int) = sum(getindex.(value(P.v),i,j)) @@ -389,7 +415,7 @@ show(io::IO,P::Proj{V,T,Λ}) where {V,T,Λ<:Real} = print(io,isone(P.λ) ? "" : show(io::IO,P::Proj{V,T,Λ}) where {V,T,Λ} = print(io,"(",P.λ,")Proj(",P.v,")") #Chain{V}(P::Proj{V,T}) where {V,T<:Chain{V,1,<:TensorNested}} = sum(Chain.(value(P.v))) -Chain{V}(P::Proj{V,T}) where {V,T<:Simplex{V}} = sum(outer.(value(P.v).*value(P.λ),P.v)) +Chain{V}(P::Proj{V,<:Chain{W,1,<:Chain}}) where {V,W} = sum(outer.(value(P.v).*value(P.λ),value(P.v))) Chain{V}(P::Proj{V}) where V = outer(P.v*P.λ,P.v) Chain(P::Proj{V}) where V = Chain{V}(P) @@ -401,12 +427,20 @@ struct Dyadic{V,X,Y} <: TensorNested{V,X} end Dyadic(x::X,y::Y) where {X<:TensorGraded,Y<:TensorGraded{V}} where V = Dyadic{V}(x,y) -Dyadic(P::Projector) = Dyadic(P.v,P.v) +Dyadic(P::Projector) = Dyadic(P.v*P.λ,P.v) Dyadic(D::Dyadic) = D (P::Dyadic)(x) = contraction(P,x) +function (T::Dyadic{V})(x::TensorAlgebra{V},y::TensorAlgebra{V}) where V + vecdot(contraction(T,x),y) +end + +Base.expm1(P::Dyadic) = expm1(Endomorphism(P)) +Base.exp(P::Dyadic) = exp(Endomorphism(P)) +Base.log(P::Dyadic) = log(Endomorphism(P)) getindex(P::Dyadic,i::Int,j::Int) = P.x[i]*P.y[j] +Base.transpose(P::Dyadic) = Dyadic(P.y,P.x) show(io::IO,P::Dyadic) = print(io,"(",P.x,")⊗(",P.y,")") @@ -420,8 +454,25 @@ struct DiagonalOperator{V,T<:TensorAlgebra{V}} <: TensorNested{V,T} DiagonalOperator{V}(t::T) where {V,T<:TensorAlgebra{V}} = new{V,T}(t) DiagonalOperator(t::T) where {V,T<:TensorAlgebra{V}} = new{V,T}(t) end +const DiagonalMorphism{V,T<:Chain{V,1}} = DiagonalOperator{V,T} +const DiagonalOutermorphism{V,T<:Multivector{V}} = DiagonalOperator{V,T} +export DiagonalMorphism, DiagonalOutermorphism +DiagonalMorphism(t::TensorGraded{V,1} where V) = DiagonalOperator(Chain(t)) +DiagonalMorphism(t::DiagonalOutermorphism) = DiagonalOperator(value(t)(Val(1))) +DiagonalOutermorphism(t::Multivector) = DiagonalOperator(Multivector(t)) +DiagonalOutermorphism(t::Chain{V,1} where V) = outermorphism(DiagonalOperator(t)) +DiagonalOutermorphism(t::DiagonalMorphism) = outermorphism(t) +DiagonalOutermorphism(t::AbstractMatrix) = outermorphism(DiagonalOperator(t)) +DiagonalMorphism(t::AbstractMatrix) = DiagonalOperator(t) +DiagonalOperator(t::AbstractMatrix) = DiagonalOperator{Submanifold(@inbounds size(t)[1])}(t) +DiagonalOutermorphism{V}(t::AbstractMatrix) where V = outermorphism(DiagonalOperator{V}(t)) +DiagonalMorphism{V}(t::AbstractMatrix) where V = DiagonalOperator{V}(t) +DiagonalOperator{V}(m::AbstractMatrix) where V = DiagonalOperator(Chain{V}(getindex.(Ref(m),list(1,mdims(V)),list(1,mdims(V))))) (T::DiagonalOperator{V})(x::TensorAlgebra{V}) where V = contraction(T,x) +function (T::DiagonalOperator{V})(x::TensorAlgebra{V},y::TensorAlgebra{V}) where V + vecdot(contraction(T,x),y) +end value(t::DiagonalOperator) = t.v matrix(m::DiagonalOperator) = matrix(TensorOperator(m)) @@ -433,18 +484,21 @@ Base.zero(t::Type{<:DiagonalOperator{V,T}}) where {V,T} = DiagonalOperator(zero( scalar(m::DiagonalOperator) = tr(m)/length(value(m)) LinearAlgebra.tr(m::DiagonalOperator) = sum(value(value(m))) -LinearAlgebra.det(m::DiagonalOperator{V,<:Chain}) where V = Chain{V,mdims(V)}(prod(value(value(m)))) -LinearAlgebra.det(m::DiagonalOperator{V,<:Multivector}) where V = value(m)(Val(mdims(V))) -compound(m::DiagonalOperator{V,<:Chain{V,1}},::Val{0}) where V = DiagonalOperator(Chain{V,0}(1)) -@generated function compound(m::DiagonalOperator{V,<:Chain{V,1}},::Val{G}) where {V,G} +LinearAlgebra.det(m::DiagonalMorphism{V}) where V = Chain{V,mdims(V)}(prod(value(value(m)))) +LinearAlgebra.det(m::DiagonalOutermorphism{V}) where V = value(m)(Val(mdims(V))) +compound(m::DiagonalMorphism{V},::Val{0}) where V = DiagonalOperator(Chain{V,0}(1)) +@generated function compound(m::DiagonalMorphism{V},::Val{G}) where {V,G} Expr(:call,:DiagonalOperator,Expr(:call,:(Chain{V,G}),Expr(:call,Values,[Expr(:call,:*,[:(@inbounds m.v[$i]) for i ∈ indices(j)]...) for j ∈ indexbasis(mdims(V),G)]...))) end -@generated function outermorphism(m::DiagonalOperator{V,<:Chain{V,1}}) where V +@generated function outermorphism(m::DiagonalMorphism{V}) where V Expr(:call,:DiagonalOperator,Expr(:call,:(Multivector{V}),Expr(:call,Values,1,[Expr(:call,:*,[:(@inbounds m.v[$i]) for i ∈ indices(j)]...) for j ∈ indexbasis(mdims(V))[list(2,tdims(V))]]...))) end -for op ∈ (:(Base.inv),:(Base.exp),:(Base.log)) - @eval $op(t::DiagonalOperator) = DiagonalOperator(map($op,value(t))) +for op ∈ (:(Base.inv),:(Base.exp),:(Base.expm1),:(Base.log)) + @eval begin + $op(t::DiagonalMorphism) = DiagonalOperator(map($op,value(t))) + $op(t::DiagonalOutermorphism) = outermorphism(DiagonalOperator(map($op,value(t)(Val(1))))) + end end _axes(t::DiagonalOperator) = (Base.OneTo(length(t.v)),Base.OneTo(length(t.v))) @@ -470,8 +524,20 @@ struct TensorOperator{V,W,T<:TensorAlgebra{V,<:TensorAlgebra{W}}} <: TensorNeste TensorOperator(t::T) where {V,W,T<:TensorAlgebra{V,<:TensorAlgebra{W}}} = new{V,W,T}(t) end -Endomorphism{V,T<:TensorAlgebra{V,<:TensorAlgebra{V}}} = TensorOperator{V,V,T} +const Endomorphism{V,T<:TensorAlgebra{V,<:TensorAlgebra{V}}} = TensorOperator{V,V,T} +Endomorphism(t::TensorAlgebra{V,<:TensorAlgebra{V}}) where V = TensorOperator{V,V}(t) + (T::TensorOperator{V})(x::TensorAlgebra{V}) where V = contraction(T,x) +function (T::TensorOperator{V,W})(x::TensorAlgebra{V},y::TensorAlgebra{W}) where {V,W} + vecdot(contraction(T,x),y) +end + +macro TensorOperator(ex) + TensorOperator(eval(ex)) +end +macro Endomorphism(ex) + Endomorphism(eval(ex)) +end value(t::TensorOperator) = t.v matrix(m::TensorOperator) = matrix(value(m)) @@ -479,6 +545,7 @@ compound(m::TensorOperator,g) = TensorOperator(compound(value(m),g)) compound(m::TensorOperator,g::Integer) = TensorOperator(compound(value(m),g)) getindex(t::TensorOperator,i::Int,j::Int) = value(value(t.v)[j])[i] getindex(t::TensorOperator,i::Int) = value(t.v)[i] +Base.transpose(t::TensorOperator) = TensorOperator(transpose(value(t))) scalar(m::Endomorphism) = tr(m)/length(value(m)) LinearAlgebra.tr(m::Endomorphism) = tr(value(m)) LinearAlgebra.det(t::TensorOperator) = ∧(value(t)) @@ -486,16 +553,29 @@ LinearAlgebra.det(t::TensorOperator) = ∧(value(t)) Base.zero(t::TensorOperator) = TensorOperator(zero(value(t))) Base.zero(t::Type{<:TensorOperator{V,W,T}}) where {V,W,T} = TensorOperator(zero(T)) -for op ∈ (:(Base.inv),) +Base.log(t::Endomorphism{V,<:Chain}) where V = Endomorphism{V}(log(Matrix(t))) +for op ∈ (:(Base.inv),:(Base.exp),:(Base.expm1)) @eval $op(t::Endomorphism{V,<:Chain}) where V = TensorOperator($op(value(t))) end -TensorOperator(t::DiagonalOperator{V,<:Chain{V,G}}) where {V,G} = TensorOperator(Chain{V,G}(value(value(t)).*chainbasis(V,G))) -TensorOperator(t::DiagonalOperator{V,<:Spinor{V,G}}) where {V,G} = TensorOperator(Spinor{V}(value(value(t)).*evenbasis(V))) -TensorOperator(t::DiagonalOperator{V,<:AntiSpinor{V,G}}) where {V,G} = TensorOperator(AntiSpinor{V}(value(value(t)).*oddbasis(V))) -TensorOperator(t::DiagonalOperator{V,<:Multivector{V,G}}) where {V,G} = TensorOperator(Multivector{V}(value(value(t)).*Λ(V).b)) -TensorOperator{V,W}(m::Matrix) where {V,W} = TensorOperator(Chain{V}(Chain{W,1}.(getindex.(Ref(m),:,list(1,size(m)[2]))))) - +Endomorphism(t::Projector) = Endomorphism(Chain(t)) +Endomorphism(t::Dyadic) = Endomorphism(Chain(t)) +@generated Endomorphism(t::DiagonalOperator{V,<:Chain{V,G}}) where {V,G} = :(Endomorphism(Chain{V,G}(value(value(t)).*$(Chain.(chainbasis(V,G)))))) +@generated Endomorphism(t::DiagonalOperator{V,<:Spinor{V,G}}) where {V,G} = :(Endomorphism(Spinor{V}(value(value(t)).*$(Spinor.(evenbasis(V)))))) +@generated Endomorphism(t::DiagonalOperator{V,<:AntiSpinor{V,G}}) where {V,G} = :(Endomorphism(AntiSpinor{V}(value(value(t)).*$(CoSpinor.(oddbasis(V)))))) +@generated Endomorphism(t::DiagonalOutermorphism{V}) where V = :(Endomorphism(Multivector{V}(value(value(t)).*$(Multivector(Λ(V).b))))) +Endomorphism(m::AbstractMatrix) = Endomorphism{Submanifold(@inbounds size(m)[1])}(m) + +TensorOperator(t::Projector) = TensorOperator(Chain(t)) +TensorOperator(t::Dyadic) = TensorOperator(Chain(t)) +@generated TensorOperator(t::DiagonalOperator{V,<:Chain{V,G}}) where {V,G} = :(TensorOperator(Chain{V,G}(value(value(t)).*$(Chain.(chainbasis(V,G)))))) +@generated TensorOperator(t::DiagonalOperator{V,<:Spinor{V,G}}) where {V,G} = :(TensorOperator(Spinor{V}(value(value(t)).*$(Spinor.(evenbasis(V)))))) +@generated TensorOperator(t::DiagonalOperator{V,<:AntiSpinor{V,G}}) where {V,G} = :(TensorOperator(AntiSpinor{V}(value(value(t)).*$(CoSpinor.(oddbasis(V)))))) +@generated TensorOperator(t::DiagonalOutermorphism{V}) where V = :(TensorOperator(Multivector{V}(value(value(t)).*$(Multivector(Λ(V).b))))) +TensorOperator(m::AbstractMatrix) = TensorOperator{Submanifold.(size(m))...}(m) +TensorOperator{V,W}(m::AbstractMatrix) where {V,W} = TensorOperator(Chain{V}(Chain{W,1}.(getindex.(Ref(m),:,list(1,mdims(V)))))) + +SpectralOperator(t::Endomorphism) = eigen(t) @generated function DiagonalOperator(t::Endomorphism{V,<:Chain{V,G}}) where {V,G} Expr(:call,:DiagonalOperator,Expr(:call,:(Chain{V,G}),[:(t[$i,$i]) for i ∈ list(1,binomial(mdims(V),G))]...)) end @@ -573,6 +653,16 @@ end end (T::Outermorphism{V})(x::TensorAlgebra{V}) where V = contraction(T,x) +function (T::Outermorphism{V})(x::TensorAlgebra{V},y::TensorAlgebra{V}) where V + vecdot(contraction(T,x),y) +end + +export @Outermorphism +macro Outermorphism(ex) + Outermorphism(Endomorphism(eval(ex))) +end + +Outermorphism(t::AbstractMatrix) = Outermorphism(Endomorphism(t)) Outermorphism(t::Simplex) = outermorphism(t) Outermorphism(t::Endomorphism{V,<:Simplex}) where V = outermorphism(value(t)) outermorphism(t::Endomorphism{V,<:Simplex}) where V = outermorphism(value(t)) @@ -580,6 +670,7 @@ DiagonalOperator(t::Outermorphism) = outermorphism(DiagonalOperator(TensorOperat value(t::Outermorphism) = t.v matrix(m::Outermorphism) = matrix(TensorOperator(m)) getindex(t::Outermorphism{V},i::Int) where V = iszero(i) ? Chain{V,0}((Chain(One(V)),)) : t.v[i] +Base.transpose(m::Outermorphism) = Outermorphism(map(transpose,value(m))) scalar(m::Outermorphism{V}) where V = tr(m)/(1<