-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Non monomial basis #21
Conversation
What's failing now are the |
@blegat I'm not trying to get tests running now. (given the number of planned changes it is a bit pointless., I'm trying to get the implicit/explicit Bases running on my examples; e.g. with G = PermGroup(perm"(1,2,3,4,5,6,7,8)", perm"(1,2)")
db = SA.DiracBasis{UInt32}(G) # <: ImplicitBasis{UInt32, eltype(G)} for an iterable G
mstr = SA.LazyMStructure(db)
g, h = rand(G, 2); and function Base.show(io::IO, sc::SA.AbstractCoefficients)
if iszero(sc)
print(io, zero(valtype(sc)))
else
for (i, (k, v)) in enumerate(pairs(sc))
print(io, v, '·', k)
i == length(pairs(sc)) && break
print(io, " + ")
end
end
end I can do now: julia> mstr[g, h] == SA.DiracDelta(g * h)
true
julia> x = SA.SparseCoefficients([one(G), g], [1, -1])
1·() + -1·(1,6,5,7,2,8,3,4)
julia> y = sc = SA.SparseCoefficients([one(G), inv(g)], [1, -1])
1·() + -1·(1,4,3,8,2,7,5,6)
julia> res = zero(x)
0
julia> SA.mul!(mstr, res, x, y); res
┌ Error: in __canonicalize!: Not implemented yet
└ @ StarAlgebras ~/.julia/dev/StarAlgebras/src/coefficients.jl:71
1·() + -1·(1,4,3,8,2,7,5,6) + -1·(1,6,5,7,2,8,3,4) + 1·() 🎉 Looks good to me even without implementing integer access to What I don't quite like at the moment is that I had to implement a specialized Base.getindex(::LazyMStructure{I,<:DiracBasis{T}}, x::T, y::T) where {I,T} It doesn't feel right... Also: The concept of |
It's working with chebyshev polynomials now, see JuliaAlgebra/MultivariateBases.jl#23
|
@blegat Sure, we could switch to storing pairs |
I got both implicit ( with some preparation using Revise
using StarAlgebras
import StarAlgebras as SA
using PermutationGroups
import PermutationGroups.AP as AP
SA.star(x::Number) = x'
SA.star(g::AP.AbstractPermutation) = inv(g)
struct Lex <: Base.Order.Ordering end
function Base.lt(::Lex, p::AP.AbstractPermutation, q::AP.AbstractPermutation)
for i in Base.OneTo(min(AP.degree(p), AP.degree(q)))
ip = i^p
iq = i^q
if ip < iq
return true
elseif ip > iq
return false
end
end
return AP.degree(p) < AP.degree(q)
end
Base.isless(p::AP.AbstractPermutation, q::AP.AbstractPermutation) =
Base.lt(Lex(), p, q)
G = PermGroup(perm"(1,2,3,4,5,6,7,8)", perm"(1,2)") # group of order 40320 one can run now: db = SA.DiracBasis{UInt32}(G)
RG = SA.StarAlgebra(G, db)
g, h = rand(G, 2)
x = SA.SparseCoefficients([one(G), g], [1, -1])
X = SA.AlgebraElement(x, RG)
y = SA.SparseCoefficients([one(G), inv(g)], [1, -1])
Y = SA.AlgebraElement(y, RG)
xy = SA.SparseCoefficients([one(G), g, inv(g)], [2, -1, -1])
XY = SA.AlgebraElement(xy, RG)
@assert X != Y
@assert X' == Y
@assert RG.mstructure[g, h] == SA.DiracDelta(g * h)
@assert X*Y == XY But also this: RGf = let G = G, g = g, h = h
fb = let (g, h) = (g, h)
# somehow generate enough elements of G to have
# a non-trivial multiplication table
for a in (g, h, inv(g), inv(h), one(g))
for b in (g, h, inv(g), inv(h), one(g))
SA.__cache(db, a * b)
end
end
# elts must be star-invariant
elts = union(db.basis, SA.star.(db.basis))
SA.FixedBasis{UInt32}(elts)
end
k = max(fb[g], fb[h], fb[inv(g)], fb[inv(h)])
mtbl = SA.MTable(fb, size=(k, k))
StarAlgebra(G, fb, mtbl)
end
let fb = SA.basis(RGf), g = g
k = fb[g]
@assert isone(fb[k] * fb[-signed(k)])
end
using SparseArrays
xf = sparsevec([fb[one(G)], fb[g]], [1, -1], length(fb))
Xf = AlgebraElement(xf, RGf)
yf = sparsevec([fb[one(G)], fb[inv(g)]], [1, -1], length(fb))
Yf = AlgebraElement(yf, RGf)
@assert Xf == Yf'
@assert (Xf')' == Xf
@assert Xf * Xf' == Xf' * Xf |
Ok, more input/experimentation here. The following fits my usecase (where f = # polynomial, AlgebraElement, etc, possibly written in different basis
g = # polynomial, AlgebraElement, etc, possibly written in different basis
function +(f, g)
A = parent(f)
res = coeffs(f) + coeffs(g, basis(A))
return AlgebraElement(res, A)
end
function *(f, g)
A = parent(f)
mstr = mstructure(A)
res = mul(mstr, coeffs(f), coeffs(g, basis(A)))
return AlgebraElement(res, A)
end To spell out assumptions:
@blegat I've implemented both implicit, fixed, and augmented (consisting of (1-x)) basis and it seems to be a valid design. what do you think? |
What if |
function *(f, g)
A = parent(f)
mop = moperator(A)
res = mop(coeffs(f), coeffs(g, basis(A)))
return AlgebraElement(res, A)
end |
src/bases.jl
Outdated
""" | ||
abstract type ImplicitBasis{T,I} <: AbstractBasis{T,I} end | ||
|
||
mutable struct DiracBasis{T,I,S,St} <: ImplicitBasis{T,I} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mutable struct DiracBasis{T,I,S,St} <: ImplicitBasis{T,I} | |
mutable struct Basis{T,I,S,St} <: ImplicitBasis{T,I} |
src/bases.jl
Outdated
dict::Dict{T,I} | ||
object::S # any iterable | ||
state::St | ||
lock::Threads.SpinLock |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a field which is *
by default and contains the multiplicative structure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mstructure(::T, ::T)
should be defined
|
|
things considered as AbstractCoefficients:
|
struct AddMul{M}
mstr::M
end
function MA.operate!(::AddMul{Cheby}, accumulator, a, b) # the new unsafe_append!
MA.operate!(MA.add_mul, accumulator, 1/2, ...) # e.g. in Chebyshev basis we add two terms
MA.operate!(MA.add_mul, accumulator, -1/2, ...)
return result
end
struct BuildContext{C}
inner::C
end
function MA.operate!(::MA.add_mul, accumulator::BuildContext, a, b) # the new unsafe_append!
MA.operate!(UnsafeAdd(), accumulator.inner, a, b)
return result
end
function MA.operate!(::UnsafeAdd, coef::SparseCoefficients, a, b) # the new unsafe_append!
push!(coef.values, a)
push!(coef.basis_elements, b)
return coef
end |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #21 +/- ##
==========================================
- Coverage 98.60% 93.51% -5.10%
==========================================
Files 8 14 +6
Lines 358 632 +274
==========================================
+ Hits 353 591 +238
- Misses 5 41 +36
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
653d90d
to
2cb891f
Compare
I'm reasonably happy with this coverage. |
Base._return_type -> MA.promote_operation
Add eachindex back
* Assume mutability for canonical * Fix allocation test * Debug for Julia v1.6 * Use 0.7
Fix all broken tests but one
🎉 |
This is not even a working code, but a place where we can discuss more concretely
What still needs to be implemented:
IndexType
?)@blegat