diff --git a/src/ACSetInterface.jl b/src/ACSetInterface.jl index e78fda1..41c2c5b 100644 --- a/src/ACSetInterface.jl +++ b/src/ACSetInterface.jl @@ -12,6 +12,7 @@ using Tables using PrettyTables: pretty_table using ..ColumnImplementations: AttrVar +using ..PreimageCaches: is_injective using ..Schemas: types, attrs, attrtypes @@ -250,6 +251,9 @@ function set_subpart! end # Inlined for the same reason as `subpart`. @inline function set_subpart!(acs::ACSet , parts::Union{AbstractVector{Int}, AbstractSet{Int}}, name, vals) + if is_injective(acs.subparts[name]) + clear_subpart!(acs, parts, name) + end broadcast(parts, vals) do part, val set_subpart!(acs, part, name, val) end diff --git a/src/Columns.jl b/src/Columns.jl index fd72598..bb0e1ea 100644 --- a/src/Columns.jl +++ b/src/Columns.jl @@ -10,7 +10,7 @@ using Reexport @reexport using ..PreimageCaches import ..Mappings: view_with_default -import ..PreimageCaches: preimage, preimage_multi +import ..PreimageCaches: preimage, preimage_multi, is_injective # Columns ######### @@ -94,4 +94,6 @@ view_with_default(c::Column, xs, def) = ColumnView(c, xs, def) Base.size(c::ColumnView) = size(c.indices) +is_injective(c::Column) = is_injective(c.pc) + end diff --git a/src/PreimageCaches.jl b/src/PreimageCaches.jl index 205fe8a..7919084 100644 --- a/src/PreimageCaches.jl +++ b/src/PreimageCaches.jl @@ -35,6 +35,7 @@ performance implications. - [`preimage`](@ref) - [`assign!`](@ref) - [`unassign!`](@ref) +- [`is_injective`](@ref) (defaults to false if not implemented) """ abstract type PreimageCache{S,T} end @@ -94,6 +95,14 @@ Remove `x` from the preimage of `y`. """ function unassign! end +""" +Whether or not the cache imposes an injectivity constraint. (default: false) +""" +is_injective(::PreimageCache)::Bool = false + +# Caches +######## + """ The trivial preimage mapping. It just computes preimages on the fly, and the operations for updating it are noops @@ -203,4 +212,6 @@ function unassign!(pc::InjectiveCache{S,T}, y::T, x::S) where {S,T} delete!(pc.inverse, y) end +is_injective(::InjectiveCache)::Bool = true + end diff --git a/test/ACSets.jl b/test/ACSets.jl index 1482e9a..de885dd 100644 --- a/test/ACSets.jl +++ b/test/ACSets.jl @@ -425,6 +425,8 @@ for lset_maker in lset_makers @test isempty(incident(lset, :foo, :label)) @test_throws Exception set_subpart!(lset, 1, :label, :bar) + set_subpart!(lset, :, :label, [:bar, :foo]) + @test subpart(lset, :, :label) == [:bar, :foo] end SchDecGraph = BasicSchema([:E,:V], [(:src,:E,:V),(:tgt,:E,:V)],