-
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
Implement quadratic forms #62
base: main
Are you sure you want to change the base?
Changes from 13 commits
c5c1cfa
41b20a4
82d0cc8
feb307c
0ea0688
5ca08fb
ab37477
f35b2a9
51d67fe
3323cb8
6020a6d
1eed904
8c9a842
e9e408a
62b9555
cb27cca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,52 +31,74 @@ When the product is not representable faithfully, | |
""" | ||
abstract type MultiplicativeStructure end | ||
|
||
""" | ||
struct UnsafeAddMul{M<:Union{typeof(*),MultiplicativeStructure}} | ||
structure::M | ||
end | ||
|
||
The value of `(op::UnsafeAddMul)(a, b, c)` is `a + structure(b, c)` | ||
where `a` is not expected to be canonicalized before the operation `+` | ||
and should not be expected to be canonicalized after either. | ||
""" | ||
struct UnsafeAddMul{M<:Union{typeof(*),MultiplicativeStructure}} | ||
structure::M | ||
end | ||
|
||
function MA.operate_to!(res, ms::MultiplicativeStructure, args::Vararg{Any,N}) where {N} | ||
""" | ||
operate_to!(res, ms::MultiplicativeStructure, A, B[, α = true]) | ||
kalmarek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Compute `α·A·B` storing the result in `res`. Return `res`. | ||
|
||
`res` is assumed to behave like `AbstractCoefficients` and not aliased with any | ||
other arguments. | ||
`A` and `B` are assumed to behave like `AbstractCoefficients`, while `α` will | ||
be treated as a scalar. | ||
|
||
Canonicalization of the result happens only once at the end of the operation. | ||
""" | ||
function MA.operate_to!( | ||
res, | ||
ms::MultiplicativeStructure, | ||
args::Vararg{Any,N}, | ||
) where {N} | ||
if any(Base.Fix1(===, res), args) | ||
throw(ArgumentError("No alias allowed")) | ||
throw( | ||
ArgumentError( | ||
"Aliasing arguments in multiplication is not supported", | ||
), | ||
) | ||
end | ||
MA.operate!(zero, res) | ||
MA.operate!(UnsafeAddMul(ms), res, args...) | ||
res = MA.operate!(UnsafeAddMul(ms), res, args...) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With |
||
MA.operate!(canonical, res) | ||
return res | ||
end | ||
|
||
function MA.operate!(::UnsafeAddMul, res, c) | ||
for (k, v) in nonzero_pairs(c) | ||
struct UnsafeAdd end | ||
|
||
function MA.operate!(::UnsafeAdd, res, b) | ||
blegat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for (k, v) in nonzero_pairs(b) | ||
unsafe_push!(res, k, v) | ||
end | ||
return res | ||
end | ||
|
||
function MA.operate!(op::UnsafeAddMul, res, b, c, args::Vararg{Any, N}) where {N} | ||
for (kb, vb) in nonzero_pairs(b) | ||
for (kc, vc) in nonzero_pairs(c) | ||
for (k, v) in nonzero_pairs(op.structure(kb, kc)) | ||
function MA.operate!(op::UnsafeAddMul, res, A, B, α) | ||
blegat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for (kA, vA) in nonzero_pairs(A) | ||
for (kB, vB) in nonzero_pairs(B) | ||
for (k, v) in nonzero_pairs(op.structure(kA, kB)) | ||
cfs = MA.@rewrite α * vA * vB * v | ||
MA.operate!( | ||
op, | ||
UnsafeAdd(), | ||
res, | ||
SparseCoefficients((_key(op.structure, k),), (vb * vc * v,)), | ||
args..., | ||
SparseCoefficients((_key(op.structure, k),), (cfs,)), | ||
) | ||
end | ||
end | ||
end | ||
return res | ||
end | ||
|
||
function MA.operate!(op::UnsafeAddMul, res, A, B, C, α) | ||
for (kA, vA) in nonzero_pairs(A) | ||
for (kB, vB) in nonzero_pairs(B) | ||
cfs = MA.@rewrite α * vA * vB | ||
MA.operate!(op, res, op.structure(kA, kB), C, cfs) | ||
end | ||
end | ||
return res | ||
end | ||
|
||
struct DiracMStructure{Op} <: MultiplicativeStructure | ||
op::Op | ||
end | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,84 @@ | ||||||
""" | ||||||
QuadraticForm(Q) | ||||||
QuadraticForm{star}(Q) | ||||||
A simple wrapper for representing a quadratic form. | ||||||
|
||||||
`QuadraticForm(Q)` represents an honest quadratic form, however in the context | ||||||
of `*`-algebras a more canonical object is a **sesquilinear form** which can be | ||||||
constructed as `QuadraticForm{star}(Q)`. | ||||||
|
||||||
Both objects are defined by matrix coefficients with respect to their bases `b`, | ||||||
i.e. their values at `i`-th and `j`-th basis elements: | ||||||
`star.(b)·Q·b = ∑ᵢⱼ Q[i,j]·star(b[i])·b[j]`. | ||||||
|
||||||
# Necessary methods: | ||||||
* `basis(Q)` - a **finite** basis `b` of the quadratic form; | ||||||
* `Base.getindex(Q, i::T, j::T)` - the value at `i`-th and `j`-th basis elements | ||||||
where `T` is the type of indicies of `basis(Q)`; | ||||||
* `Base.eltype(Q)` - the type of `Q[i,j]·star(b[i])·b[j]`. | ||||||
""" | ||||||
struct QuadraticForm{T,involution} | ||||||
Q::T | ||||||
QuadraticForm(Q) = new{typeof(Q),identity}(Q) | ||||||
QuadraticForm{star}(Q) = new{typeof(Q),star}(Q) | ||||||
end | ||||||
|
||||||
Base.eltype(qf::QuadraticForm) = eltype(qf.Q) | ||||||
basis(qf::QuadraticForm) = basis(qf.Q) | ||||||
Base.getindex(qf::QuadraticForm, i::T, j::T) where {T} = qf.Q[i, j] | ||||||
|
||||||
function MA.operate_to!( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do I read correctly, that you need to add several quadratic forms together? function MA.operate_to!(res, ms::MultiplicativeStructure, Qs::Vararg{<:QuadraticForm})
MA.operate!(zero, res)
for Q in Qs
MA.operate!(ms, res, Q)
end
MA.operate!(canonical, res)
return res
end
function MA.operate!(ms::MultiplicativeStructure, res, Q::QuadraticForm{T,ε}) where {T,ε}
op = UnsafeAddMul(ms)
for (i, b1) in pairs(basis(Q))
b1★ = ε(b1)
for (j, b2) in pairs(basis(Q))
MA.operate!(op, res, coeffs(b1★), coeffs(b2), Q[i, j])
end
end
return res
end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be much easier to push this over the finish line had you provided the use-cases you have in mind for SoS as I asked many a times... :D There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm as lost in the design space as you are ^^
So the use case is p = zero(...)
for (q, g) in zip(...)
MA.operate!(UnsafeAddMul(...), p, QuadraticForm(q), g)
end |
||||||
res, | ||||||
ms::MultiplicativeStructure, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the plan for this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, this signature needs to change. What we want here is to say: Is (this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is precedent for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
Q::QuadraticForm, | ||||||
args..., | ||||||
) | ||||||
MA.operate!(zero, res) | ||||||
MA.operate!(UnsafeAddMul(ms), res, Q, args...) | ||||||
MA.operate!(canonical, res) | ||||||
return res | ||||||
end | ||||||
|
||||||
function MA.operate!( | ||||||
op::UnsafeAddMul, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that we have |
||||||
res, | ||||||
Q::QuadraticForm{T,ε}, | ||||||
) where {T,ε} | ||||||
for (i, b1) in pairs(basis(Q)) | ||||||
b1★ = ε(b1) | ||||||
for (j, b2) in pairs(basis(Q)) | ||||||
MA.operate!(op, res, coeffs(b1★), coeffs(b2), Q[i, j]) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So every basis element should implement There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if the elements of the basis are just group elements There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we see AlgebraElement, this implementation is correct. Otherwise we should multiply b1 and b2 using the multiplicative structure There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can just return They are not just group elements, they are So far it seems that you can place in a basis something sortable (unless you There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you use arbitrary There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would just call some new internal function and distinguish two cases with multiple dispatch
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't just place group elements in basis, you need to pick a multiplicative structure. It could be e.g. Does your element behave like coefficients? then we could define There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but in general, I'm not convinced that this quadratic form is a good design. Let's brainstorm for a bit where should all Can you formulate a concrete example specifying:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok let me formulate a use case in the main thread |
||||||
end | ||||||
end | ||||||
end | ||||||
|
||||||
function MA.operate!( | ||||||
op::UnsafeAddMul, | ||||||
res, | ||||||
Q::QuadraticForm{T,ε}, | ||||||
p, | ||||||
) where {T,ε} | ||||||
for (i, b1) in pairs(basis(Q)) | ||||||
b1★ = ε(b1) | ||||||
for (j, b2) in pairs(basis(Q)) | ||||||
MA.operate!(op, res, coeffs(b1★), coeffs(b2), coeffs(p), Q[i, j]) | ||||||
end | ||||||
end | ||||||
end | ||||||
|
||||||
""" | ||||||
AlgebraElement(qf::QuadraticForm, A::AbstractStarAlgebra) | ||||||
Construct an algebra element in `A` representing quadratic form `qf`. | ||||||
|
||||||
!!! warning | ||||||
It is assumed that all basis elements of `qf` belong to `A`, or at least | ||||||
that `keys` of their coefficients can be found in the basis of `A`. | ||||||
""" | ||||||
function AlgebraElement(qf::QuadraticForm, A::AbstractStarAlgebra) | ||||||
@assert all(b -> parent(b) == A, basis(qf)) | ||||||
res = zero(eltype(qf), A) | ||||||
MA.operate_to!(coeffs(res), mstructure(A), qf) | ||||||
return res | ||||||
end | ||||||
|
||||||
(A::AbstractStarAlgebra)(qf::QuadraticForm) = AlgebraElement(qf, A) |
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.
Why don't we take the conjugation?