From 9afa147f6b9856a7998415276729c89e94d57169 Mon Sep 17 00:00:00 2001 From: slwu89 Date: Sat, 30 Sep 2023 16:35:48 -0700 Subject: [PATCH 1/9] tmp file with cases to fix --- tmp.jl | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tmp.jl diff --git a/tmp.jl b/tmp.jl new file mode 100644 index 0000000..22d5ff2 --- /dev/null +++ b/tmp.jl @@ -0,0 +1,42 @@ +using Revise, ACSets + +# ------------------------------------------------------------ +# test for Homs + +MySch = BasicSchema( + [:A,:B], [(:f,:A,:B)], [], [] +) + +@acset_type MyDataNoIdx(MySch) +@acset_type MyDataIdx(MySch, index=[:f]) +@acset_type MyDataInjIdx(MySch, unique_index=[:f]) + +data_noidx = @acset MyDataNoIdx begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +data_idx = @acset MyDataIdx begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +data_inj = @acset MyDataInjIdx begin + A = 5 + B = 5 + f = [1,2,3,4,5] + end + +rem_parts!(data_noidx, :B, 1:3) +rem_parts!(data_idx, :B, 1:3) +rem_parts!(data_inj, :B, 1:3) + +incident(data_noidx, 0, :f) +incident(data_idx, 0, :f) +incident(data_inj, 0, :f) + +# would be nice if incident could do +findall(data_noidx[:,:f] .== 0) +findall(data_idx[:,:f] .== 0) \ No newline at end of file From de5a198eb95b451a58d214f689863aadcade30b0 Mon Sep 17 00:00:00 2001 From: slwu89 Date: Sun, 1 Oct 2023 10:23:35 -0700 Subject: [PATCH 2/9] tests fail for MarkAsDeleted and BitSet part types --- src/ACSetInterface.jl | 8 ++- src/DenseACSets.jl | 15 ++++++ test/ACSets.jl | 4 ++ tmp.jl | 121 +++++++++++++++++++++++++++--------------- 4 files changed, 105 insertions(+), 43 deletions(-) diff --git a/src/ACSetInterface.jl b/src/ACSetInterface.jl index e78fda1..18932f4 100644 --- a/src/ACSetInterface.jl +++ b/src/ACSetInterface.jl @@ -4,7 +4,8 @@ export ACSet, acset_schema, acset_name, dom_parts, subpart_type, add_part!, add_parts!, set_subpart!, set_subparts!, clear_subpart!, rem_part!, rem_parts!, cascading_rem_part!, cascading_rem_parts!, gc!, copy_parts!, copy_parts_only!, disjoint_union, tables, pretty_tables, - @acset, constructor, PartsType, DenseParts, MarkAsDeleted, rem_free_vars! + @acset, constructor, undefined_subparts, PartsType, DenseParts, MarkAsDeleted, + rem_free_vars! using MLStyle: @match using StaticArrays: StaticArray @@ -391,6 +392,11 @@ Get a nullary callable which constructs an (empty) ACSet of the same type """ function constructor end +""" +Given a hom, find which parts in its domain are undefined. +""" +function undefined_subparts end + # Pretty printing ################# diff --git a/src/DenseACSets.jl b/src/DenseACSets.jl index 5e7cc15..7f663eb 100644 --- a/src/DenseACSets.jl +++ b/src/DenseACSets.jl @@ -644,6 +644,21 @@ end ACSetInterface.cascading_rem_parts!(acs::ACSet, type, parts) = delete_subobj!(acs, Dict(type=>parts)) +function ACSetInterface.undefined_subparts(acs::StructACSet{S,Ts}, f::Symbol) where {S,Ts} + _undefined_subparts(acs, S, f) +end + +function ACSetInterface.undefined_subparts(acs::DynamicACSet, f::Symbol) + _undefined_subparts(acs, acs.schema, f) +end + +function _undefined_subparts(acs::SimpleACSet, S, f) + if f ∉ homs(Schema(S); just_names=true) + error("$(f) is not a hom") + end + findall([!haskey(acs.subparts[f],i) for i in dom_parts(acs,f)]) +end + # Copy Parts ############ diff --git a/test/ACSets.jl b/test/ACSets.jl index 9e0d581..e1febcb 100644 --- a/test/ACSets.jl +++ b/test/ACSets.jl @@ -32,6 +32,7 @@ dds_makers = [ ] for dds_maker in dds_makers + println("dds maker: $(dds_maker)") dds = dds_maker() @test keys(tables(dds)) == (:X,) @test nparts(dds, :X) == 0 @@ -73,7 +74,10 @@ for dds_maker in dds_makers view(dds,:Φ) isa ColumnView # Deletion. + @test_throws ErrorException undefined_subparts(dds, :X) + @test undefined_subparts(dds, :Φ) == [] rem_part!(dds, :X, 2) + @test undefined_subparts(dds, :Φ) == [1] skip=dds_maker ∈ dds_makers[[2,5,7]] @test nparts(dds, :X) == 2 @test incident(dds, 1, :Φ) == [] if dds.parts[:X] isa IntParts diff --git a/tmp.jl b/tmp.jl index 22d5ff2..98094cd 100644 --- a/tmp.jl +++ b/tmp.jl @@ -1,42 +1,79 @@ -using Revise, ACSets - -# ------------------------------------------------------------ -# test for Homs - -MySch = BasicSchema( - [:A,:B], [(:f,:A,:B)], [], [] -) - -@acset_type MyDataNoIdx(MySch) -@acset_type MyDataIdx(MySch, index=[:f]) -@acset_type MyDataInjIdx(MySch, unique_index=[:f]) - -data_noidx = @acset MyDataNoIdx begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -data_idx = @acset MyDataIdx begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -data_inj = @acset MyDataInjIdx begin - A = 5 - B = 5 - f = [1,2,3,4,5] - end - -rem_parts!(data_noidx, :B, 1:3) -rem_parts!(data_idx, :B, 1:3) -rem_parts!(data_inj, :B, 1:3) - -incident(data_noidx, 0, :f) -incident(data_idx, 0, :f) -incident(data_inj, 0, :f) - -# would be nice if incident could do -findall(data_noidx[:,:f] .== 0) -findall(data_idx[:,:f] .== 0) \ No newline at end of file +# using Revise, ACSets + +# # ------------------------------------------------------------ +# # test for Homs + +# MySch = BasicSchema( +# [:A,:B], [(:f,:A,:B)], [], [] +# ) + +# @acset_type MyDataNoIdx(MySch) +# @acset_type MyDataIdx(MySch, index=[:f]) +# @acset_type MyDataInjIdx(MySch, unique_index=[:f]) + +# data_noidx = @acset MyDataNoIdx begin +# A = 5 +# B = 5 +# f = [1,2,3,4,5] +# end + +# data_idx = @acset MyDataIdx begin +# A = 5 +# B = 5 +# f = [1,2,3,4,5] +# end + +# data_inj = @acset MyDataInjIdx begin +# A = 5 +# B = 5 +# f = [1,2,3,4,5] +# end + +# rem_parts!(data_noidx, :B, 1:3) +# rem_parts!(data_idx, :B, 1:3) +# rem_parts!(data_inj, :B, 1:3) + +# incident(data_noidx, 0, :f) +# incident(data_idx, 0, :f) +# incident(data_inj, 0, :f) + +# data_noidx.subparts[:f].m +# data_noidx.subparts[:f].m.v +# data_noidx.subparts[:f].m.defined +# data_noidx.subparts[:f].pc + +# data_idx.subparts[:f].m +# data_idx.subparts[:f].m.v +# data_idx.subparts[:f].m.defined +# data_idx.subparts[:f].pc +# data_idx.subparts[:f].pc.preimages + +# data_inj.subparts[:f].m +# data_inj.subparts[:f].m.v +# data_inj.subparts[:f].m.defined +# data_inj.subparts[:f].pc +# data_inj.subparts[:f].pc.inverse + +# # get how many parts in domain +# dom_parts(data_inj, :f) + +# # get col view +# colview = view(data_noidx,1:5,:f) + +# colview.column.m.defined + +# function test_find_undef(acs, part) +# # need to check that its really a hom +# findall([!haskey(acs.subparts[part],i) for i in dom_parts(acs,part)]) +# end + +# # would be nice if incident could do +# findall(data_noidx[:,:f] .== 0) +# test_find_undef(data_noidx,:f) +# undefined_subparts(data_noidx,:f) + +# findall(data_idx[:,:f] .== 0) +# test_find_undef(data_idx,:f) + +# findall(data_inj[:,:f] .== 0) +# test_find_undef(data_inj,:f) \ No newline at end of file From 8b6c9c0f26e173237db02ff3055ebc6a40644ce7 Mon Sep 17 00:00:00 2001 From: slwu89 Date: Sun, 1 Oct 2023 12:22:13 -0700 Subject: [PATCH 3/9] using undefined_subparts on <: MarkAsDeleted is an error --- src/DenseACSets.jl | 17 +++-- test/ACSets.jl | 13 +++- tmp.jl | 183 ++++++++++++++++++++++++++------------------- 3 files changed, 125 insertions(+), 88 deletions(-) diff --git a/src/DenseACSets.jl b/src/DenseACSets.jl index 7f663eb..d4cff7a 100644 --- a/src/DenseACSets.jl +++ b/src/DenseACSets.jl @@ -645,20 +645,25 @@ ACSetInterface.cascading_rem_parts!(acs::ACSet, type, parts) = delete_subobj!(acs, Dict(type=>parts)) function ACSetInterface.undefined_subparts(acs::StructACSet{S,Ts}, f::Symbol) where {S,Ts} - _undefined_subparts(acs, S, f) + s = Schema(S) + f ∈ homs(s; just_names=true) || error("$f is not a hom") + _undefined_subparts(acs, f, acs.parts[dom(s,f)]) end function ACSetInterface.undefined_subparts(acs::DynamicACSet, f::Symbol) - _undefined_subparts(acs, acs.schema, f) + s = Schema(acs.schema) + f ∈ homs(s; just_names=true) || error("$f is not a hom") + _undefined_subparts(acs, f, acs.parts[dom(s,f)]) end -function _undefined_subparts(acs::SimpleACSet, S, f) - if f ∉ homs(Schema(S); just_names=true) - error("$(f) is not a hom") - end +function _undefined_subparts(acs::SimpleACSet, f::Symbol, ::DenseParts) findall([!haskey(acs.subparts[f],i) for i in dom_parts(acs,f)]) end +function _undefined_subparts(acs::SimpleACSet, f::Symbol, ::MarkAsDeleted) + error("undefined_subparts only defined for homs with DenseParts domains") +end + # Copy Parts ############ diff --git a/test/ACSets.jl b/test/ACSets.jl index e1febcb..9e7186b 100644 --- a/test/ACSets.jl +++ b/test/ACSets.jl @@ -32,7 +32,6 @@ dds_makers = [ ] for dds_maker in dds_makers - println("dds maker: $(dds_maker)") dds = dds_maker() @test keys(tables(dds)) == (:X,) @test nparts(dds, :X) == 0 @@ -75,9 +74,17 @@ for dds_maker in dds_makers # Deletion. @test_throws ErrorException undefined_subparts(dds, :X) - @test undefined_subparts(dds, :Φ) == [] + if dds.parts[dom(acset_schema(dds),:Φ)] isa DenseParts + @test undefined_subparts(dds, :Φ) == [] + else + @test_throws ErrorException undefined_subparts(dds, :Φ) + end rem_part!(dds, :X, 2) - @test undefined_subparts(dds, :Φ) == [1] skip=dds_maker ∈ dds_makers[[2,5,7]] + if dds.parts[dom(acset_schema(dds),:Φ)] isa DenseParts + @test undefined_subparts(dds, :Φ) == [1] + else + @test_throws ErrorException undefined_subparts(dds, :Φ) + end @test nparts(dds, :X) == 2 @test incident(dds, 1, :Φ) == [] if dds.parts[:X] isa IntParts diff --git a/tmp.jl b/tmp.jl index 98094cd..0f149d5 100644 --- a/tmp.jl +++ b/tmp.jl @@ -1,79 +1,104 @@ -# using Revise, ACSets - -# # ------------------------------------------------------------ -# # test for Homs - -# MySch = BasicSchema( -# [:A,:B], [(:f,:A,:B)], [], [] -# ) - -# @acset_type MyDataNoIdx(MySch) -# @acset_type MyDataIdx(MySch, index=[:f]) -# @acset_type MyDataInjIdx(MySch, unique_index=[:f]) - -# data_noidx = @acset MyDataNoIdx begin -# A = 5 -# B = 5 -# f = [1,2,3,4,5] -# end - -# data_idx = @acset MyDataIdx begin -# A = 5 -# B = 5 -# f = [1,2,3,4,5] -# end - -# data_inj = @acset MyDataInjIdx begin -# A = 5 -# B = 5 -# f = [1,2,3,4,5] -# end - -# rem_parts!(data_noidx, :B, 1:3) -# rem_parts!(data_idx, :B, 1:3) -# rem_parts!(data_inj, :B, 1:3) - -# incident(data_noidx, 0, :f) -# incident(data_idx, 0, :f) -# incident(data_inj, 0, :f) - -# data_noidx.subparts[:f].m -# data_noidx.subparts[:f].m.v -# data_noidx.subparts[:f].m.defined -# data_noidx.subparts[:f].pc - -# data_idx.subparts[:f].m -# data_idx.subparts[:f].m.v -# data_idx.subparts[:f].m.defined -# data_idx.subparts[:f].pc -# data_idx.subparts[:f].pc.preimages - -# data_inj.subparts[:f].m -# data_inj.subparts[:f].m.v -# data_inj.subparts[:f].m.defined -# data_inj.subparts[:f].pc -# data_inj.subparts[:f].pc.inverse - -# # get how many parts in domain -# dom_parts(data_inj, :f) - -# # get col view -# colview = view(data_noidx,1:5,:f) - -# colview.column.m.defined - -# function test_find_undef(acs, part) -# # need to check that its really a hom -# findall([!haskey(acs.subparts[part],i) for i in dom_parts(acs,part)]) -# end - -# # would be nice if incident could do -# findall(data_noidx[:,:f] .== 0) -# test_find_undef(data_noidx,:f) -# undefined_subparts(data_noidx,:f) - -# findall(data_idx[:,:f] .== 0) -# test_find_undef(data_idx,:f) - -# findall(data_inj[:,:f] .== 0) -# test_find_undef(data_inj,:f) \ No newline at end of file +using Revise, ACSets + +# ------------------------------------------------------------ +# test for Homs + +MySch = BasicSchema( + [:A,:B], [(:f,:A,:B)], [], [] +) + +@acset_type MyDataNoIdx(MySch) +@acset_type MyDataIdx(MySch, index=[:f]) +@acset_type MyDataInjIdx(MySch, unique_index=[:f]) + +data_noidx = @acset MyDataNoIdx begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +data_idx = @acset MyDataIdx begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +data_inj = @acset MyDataInjIdx begin + A = 5 + B = 5 + f = [1,2,3,4,5] + end + +rem_parts!(data_noidx, :B, 1:3) +rem_parts!(data_idx, :B, 1:3) +rem_parts!(data_inj, :B, 1:3) + +incident(data_noidx, 0, :f) +incident(data_idx, 0, :f) +incident(data_inj, 0, :f) + +data_noidx.subparts[:f].m +data_noidx.subparts[:f].m.v +data_noidx.subparts[:f].m.defined +data_noidx.subparts[:f].pc + +data_idx.subparts[:f].m +data_idx.subparts[:f].m.v +data_idx.subparts[:f].m.defined +data_idx.subparts[:f].pc +data_idx.subparts[:f].pc.preimages + +data_inj.subparts[:f].m +data_inj.subparts[:f].m.v +data_inj.subparts[:f].m.defined +data_inj.subparts[:f].pc +data_inj.subparts[:f].pc.inverse + +# get how many parts in domain +dom_parts(data_inj, :f) + +# get col view +colview = view(data_noidx,1:5,:f) + +colview.column.m.defined + +function test_find_undef(acs, part) + # need to check that its really a hom + findall([!haskey(acs.subparts[part],i) for i in dom_parts(acs,part)]) +end + +# would be nice if incident could do +findall(data_noidx[:,:f] .== 0) +undefined_subparts(data_noidx,:f) + +findall(data_idx[:,:f] .== 0) +undefined_subparts(data_idx,:f) + +findall(data_inj[:,:f] .== 0) +undefined_subparts(data_inj,:f) + +# ------------------------------------------------------------ +# these should not fail + +@acset_type MyDataNoIdxBit(MySch, part_type=BitSetParts) +@acset_type MyDataIdxBit(MySch, index=[:f], part_type=BitSetParts) +@acset_type MyDataInjIdxBit(MySch, unique_index=[:f], part_type=BitSetParts) + +@acset_type MyDataNoIdxMark(MySch, part_type=MarkAsDeleted) +@acset_type MyDataIdxMark(MySch, index=[:f], part_type=MarkAsDeleted) +@acset_type MyDataInjIdxMark(MySch, unique_index=[:f], part_type=MarkAsDeleted) + +data = @acset MyDataNoIdxBit begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +rem_parts!(data, :B, 1:3) + + +subpart(data, :f) + +data.subparts.f + +undefined_subparts(data, :f) \ No newline at end of file From 008168ec86a6876bd5ed8fc5295498327530842c Mon Sep 17 00:00:00 2001 From: slwu89 Date: Sun, 1 Oct 2023 12:30:18 -0700 Subject: [PATCH 4/9] delete temp file --- tmp.jl | 104 --------------------------------------------------------- 1 file changed, 104 deletions(-) delete mode 100644 tmp.jl diff --git a/tmp.jl b/tmp.jl deleted file mode 100644 index 0f149d5..0000000 --- a/tmp.jl +++ /dev/null @@ -1,104 +0,0 @@ -using Revise, ACSets - -# ------------------------------------------------------------ -# test for Homs - -MySch = BasicSchema( - [:A,:B], [(:f,:A,:B)], [], [] -) - -@acset_type MyDataNoIdx(MySch) -@acset_type MyDataIdx(MySch, index=[:f]) -@acset_type MyDataInjIdx(MySch, unique_index=[:f]) - -data_noidx = @acset MyDataNoIdx begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -data_idx = @acset MyDataIdx begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -data_inj = @acset MyDataInjIdx begin - A = 5 - B = 5 - f = [1,2,3,4,5] - end - -rem_parts!(data_noidx, :B, 1:3) -rem_parts!(data_idx, :B, 1:3) -rem_parts!(data_inj, :B, 1:3) - -incident(data_noidx, 0, :f) -incident(data_idx, 0, :f) -incident(data_inj, 0, :f) - -data_noidx.subparts[:f].m -data_noidx.subparts[:f].m.v -data_noidx.subparts[:f].m.defined -data_noidx.subparts[:f].pc - -data_idx.subparts[:f].m -data_idx.subparts[:f].m.v -data_idx.subparts[:f].m.defined -data_idx.subparts[:f].pc -data_idx.subparts[:f].pc.preimages - -data_inj.subparts[:f].m -data_inj.subparts[:f].m.v -data_inj.subparts[:f].m.defined -data_inj.subparts[:f].pc -data_inj.subparts[:f].pc.inverse - -# get how many parts in domain -dom_parts(data_inj, :f) - -# get col view -colview = view(data_noidx,1:5,:f) - -colview.column.m.defined - -function test_find_undef(acs, part) - # need to check that its really a hom - findall([!haskey(acs.subparts[part],i) for i in dom_parts(acs,part)]) -end - -# would be nice if incident could do -findall(data_noidx[:,:f] .== 0) -undefined_subparts(data_noidx,:f) - -findall(data_idx[:,:f] .== 0) -undefined_subparts(data_idx,:f) - -findall(data_inj[:,:f] .== 0) -undefined_subparts(data_inj,:f) - -# ------------------------------------------------------------ -# these should not fail - -@acset_type MyDataNoIdxBit(MySch, part_type=BitSetParts) -@acset_type MyDataIdxBit(MySch, index=[:f], part_type=BitSetParts) -@acset_type MyDataInjIdxBit(MySch, unique_index=[:f], part_type=BitSetParts) - -@acset_type MyDataNoIdxMark(MySch, part_type=MarkAsDeleted) -@acset_type MyDataIdxMark(MySch, index=[:f], part_type=MarkAsDeleted) -@acset_type MyDataInjIdxMark(MySch, unique_index=[:f], part_type=MarkAsDeleted) - -data = @acset MyDataNoIdxBit begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -rem_parts!(data, :B, 1:3) - - -subpart(data, :f) - -data.subparts.f - -undefined_subparts(data, :f) \ No newline at end of file From 8ffc29e8fac68f2143b07ab9d4d38c35bac7ec34 Mon Sep 17 00:00:00 2001 From: slwu89 Date: Mon, 2 Oct 2023 17:37:15 -0700 Subject: [PATCH 5/9] address Kris' comments --- src/ACSetInterface.jl | 18 +++++++- src/DenseACSets.jl | 21 +++++---- test/ACSets.jl | 12 +---- tmp.jl | 100 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 21 deletions(-) create mode 100644 tmp.jl diff --git a/src/ACSetInterface.jl b/src/ACSetInterface.jl index 18932f4..9dfaccf 100644 --- a/src/ACSetInterface.jl +++ b/src/ACSetInterface.jl @@ -1,11 +1,11 @@ module ACSetInterface -export ACSet, acset_schema, acset_name, dom_parts, subpart_type, +export ACSet, acset_schema, acset_name, dom_parts, codom_parts, subpart_type, nparts, maxpart, parts, has_part, has_subpart, subpart, incident, add_part!, add_parts!, set_subpart!, set_subparts!, clear_subpart!, rem_part!, rem_parts!, cascading_rem_part!, cascading_rem_parts!, gc!, copy_parts!, copy_parts_only!, disjoint_union, tables, pretty_tables, @acset, constructor, undefined_subparts, PartsType, DenseParts, MarkAsDeleted, - rem_free_vars! + rem_free_vars!, parts_type using MLStyle: @match using StaticArrays: StaticArray @@ -114,6 +114,15 @@ where X is the dom of the f in the schema """ function dom_parts end +""" +Get the parts of the codomain of a morphism in an acset + +dom_parts(acs, f) == parts(acs, Y) + +where Y is the codom of the f in the schema +""" +function codom_parts end + """ Get the type assigned to a subpart in an acset, i.e. @@ -397,6 +406,11 @@ Given a hom, find which parts in its domain are undefined. """ function undefined_subparts end +""" +Get the type used to store parts IDs. +""" +parts_type(::ACSet{PT}) where {PT} = PT + # Pretty printing ################# diff --git a/src/DenseACSets.jl b/src/DenseACSets.jl index d4cff7a..1285e4a 100644 --- a/src/DenseACSets.jl +++ b/src/DenseACSets.jl @@ -498,6 +498,14 @@ end parts(acs, @ct dom(s, f)) end +@inline ACSetInterface.codom_parts(acs::StructACSet{S}, f::Symbol) where {S} = _codom_parts(acs, Val{S}, Val{f}) +@inline ACSetInterface.codom_parts(acs::DynamicACSet, f::Symbol) = runtime(_codom_parts, acs, acs.schema, f) + +@ct_enable function _codom_parts(acs, @ct(S), @ct(f)) + @ct s = Schema(S) + parts(acs, @ct codom(s, f)) +end + @inline function ACSetInterface.incident(acs::SimpleACSet, part, f::Symbol) preimage(dom_parts(acs, f), acs.subparts[f], part) end @@ -644,14 +652,8 @@ end ACSetInterface.cascading_rem_parts!(acs::ACSet, type, parts) = delete_subobj!(acs, Dict(type=>parts)) -function ACSetInterface.undefined_subparts(acs::StructACSet{S,Ts}, f::Symbol) where {S,Ts} - s = Schema(S) - f ∈ homs(s; just_names=true) || error("$f is not a hom") - _undefined_subparts(acs, f, acs.parts[dom(s,f)]) -end - -function ACSetInterface.undefined_subparts(acs::DynamicACSet, f::Symbol) - s = Schema(acs.schema) +function ACSetInterface.undefined_subparts(acs::SimpleACSet, f::Symbol) + s = acset_schema(acs) f ∈ homs(s; just_names=true) || error("$f is not a hom") _undefined_subparts(acs, f, acs.parts[dom(s,f)]) end @@ -661,7 +663,8 @@ function _undefined_subparts(acs::SimpleACSet, f::Symbol, ::DenseParts) end function _undefined_subparts(acs::SimpleACSet, f::Symbol, ::MarkAsDeleted) - error("undefined_subparts only defined for homs with DenseParts domains") + codom_ids = codom_parts(acs,f) + findall([acs.subparts[f][i] ∉ codom_ids for i in dom_parts(acs,f)]) end # Copy Parts diff --git a/test/ACSets.jl b/test/ACSets.jl index 9e7186b..1c6361a 100644 --- a/test/ACSets.jl +++ b/test/ACSets.jl @@ -74,17 +74,9 @@ for dds_maker in dds_makers # Deletion. @test_throws ErrorException undefined_subparts(dds, :X) - if dds.parts[dom(acset_schema(dds),:Φ)] isa DenseParts - @test undefined_subparts(dds, :Φ) == [] - else - @test_throws ErrorException undefined_subparts(dds, :Φ) - end + @test undefined_subparts(dds, :Φ) == [] rem_part!(dds, :X, 2) - if dds.parts[dom(acset_schema(dds),:Φ)] isa DenseParts - @test undefined_subparts(dds, :Φ) == [1] - else - @test_throws ErrorException undefined_subparts(dds, :Φ) - end + @test undefined_subparts(dds, :Φ) == [1] @test nparts(dds, :X) == 2 @test incident(dds, 1, :Φ) == [] if dds.parts[:X] isa IntParts diff --git a/tmp.jl b/tmp.jl new file mode 100644 index 0000000..6954d3c --- /dev/null +++ b/tmp.jl @@ -0,0 +1,100 @@ +using Revise, ACSets + +MySch = BasicSchema([:A,:B], [(:f,:A,:B)], [], []) + +@acset_type MyDataNoIdx(MySch) +@acset_type MyDataIdx(MySch, index=[:f]) +@acset_type MyDataInj(MySch, unique_index=[:f]) + +data_noidx = @acset MyDataNoIdx begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +data_idx = @acset MyDataIdx begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +data_inj = @acset MyDataInj begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +undefined_subparts(data_noidx, :f) +undefined_subparts(data_idx, :f) +undefined_subparts(data_inj, :f) + +rem_parts!(data_noidx, :B, 1:3) +rem_parts!(data_idx, :B, 1:3) +rem_parts!(data_inj, :B, 1:3) + +undefined_subparts(data_noidx, :f) +undefined_subparts(data_idx, :f) +undefined_subparts(data_inj, :f) + +# with non-DenseParts +@acset_type MyDataNoIdxBit(MySch, part_type=BitSetParts) +@acset_type MyDataIdxBit(MySch, index=[:f], part_type=BitSetParts) +@acset_type MyDataInjBit(MySch, unique_index=[:f], part_type=BitSetParts) + +data_noidx_bit = @acset MyDataNoIdxBit begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +data_idx_bit = @acset MyDataIdxBit begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +data_inj_bit = @acset MyDataInjBit begin + A = 5 + B = 5 + f = [1,2,3,4,5] +end + +undefined_subparts(data_noidx_bit, :f) +undefined_subparts(data_idx_bit, :f) +undefined_subparts(data_inj_bit, :f) + +rem_parts!(data_noidx_bit, :B, 1:3) +rem_parts!(data_idx_bit, :B, 1:3) +rem_parts!(data_inj_bit, :B, 1:3) + +undefined_subparts(data_noidx_bit, :f) +undefined_subparts(data_idx_bit, :f) +undefined_subparts(data_inj_bit, :f) + +# with the oddballs +dyn_acset = () -> DynamicACSet("MyData", MySch; index=[:f]) +dyn_acset_idx_bit = () -> DynamicACSet("MyData", MySch; index=[:f], part_type=MarkAsDeleted) +anon_acset = () -> AnonACSet(MySch; index=[:f]) +anon_acset_bit = () -> AnonACSet(MySch; index=[:f], part_type=MarkAsDeleted) + +data = anon_acset_bit() +add_parts!(data, :B, 5) +add_parts!(data, :A, 5, f = [1,2,3,4,5]) + +undefined_subparts(data, :f) + +rem_parts!(data, :B, 1:3) + +undefined_subparts(data, :f) + +# f=:f +# acs=data_noidx_bit + +# dom_parts(acs,f) + +# acs.subparts[f] +# acs.subparts[f] + +# codom_ids = codom_parts(acs,f) + +# findall([acs.subparts[f][i] ∉ codom_ids for i in dom_parts(acs,f)]) \ No newline at end of file From e9df73aa88fd6ab9d9f156ea9b96f836d9c5c470 Mon Sep 17 00:00:00 2001 From: slwu89 Date: Mon, 2 Oct 2023 17:37:37 -0700 Subject: [PATCH 6/9] remove accidentally commited file --- tmp.jl | 100 --------------------------------------------------------- 1 file changed, 100 deletions(-) delete mode 100644 tmp.jl diff --git a/tmp.jl b/tmp.jl deleted file mode 100644 index 6954d3c..0000000 --- a/tmp.jl +++ /dev/null @@ -1,100 +0,0 @@ -using Revise, ACSets - -MySch = BasicSchema([:A,:B], [(:f,:A,:B)], [], []) - -@acset_type MyDataNoIdx(MySch) -@acset_type MyDataIdx(MySch, index=[:f]) -@acset_type MyDataInj(MySch, unique_index=[:f]) - -data_noidx = @acset MyDataNoIdx begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -data_idx = @acset MyDataIdx begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -data_inj = @acset MyDataInj begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -undefined_subparts(data_noidx, :f) -undefined_subparts(data_idx, :f) -undefined_subparts(data_inj, :f) - -rem_parts!(data_noidx, :B, 1:3) -rem_parts!(data_idx, :B, 1:3) -rem_parts!(data_inj, :B, 1:3) - -undefined_subparts(data_noidx, :f) -undefined_subparts(data_idx, :f) -undefined_subparts(data_inj, :f) - -# with non-DenseParts -@acset_type MyDataNoIdxBit(MySch, part_type=BitSetParts) -@acset_type MyDataIdxBit(MySch, index=[:f], part_type=BitSetParts) -@acset_type MyDataInjBit(MySch, unique_index=[:f], part_type=BitSetParts) - -data_noidx_bit = @acset MyDataNoIdxBit begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -data_idx_bit = @acset MyDataIdxBit begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -data_inj_bit = @acset MyDataInjBit begin - A = 5 - B = 5 - f = [1,2,3,4,5] -end - -undefined_subparts(data_noidx_bit, :f) -undefined_subparts(data_idx_bit, :f) -undefined_subparts(data_inj_bit, :f) - -rem_parts!(data_noidx_bit, :B, 1:3) -rem_parts!(data_idx_bit, :B, 1:3) -rem_parts!(data_inj_bit, :B, 1:3) - -undefined_subparts(data_noidx_bit, :f) -undefined_subparts(data_idx_bit, :f) -undefined_subparts(data_inj_bit, :f) - -# with the oddballs -dyn_acset = () -> DynamicACSet("MyData", MySch; index=[:f]) -dyn_acset_idx_bit = () -> DynamicACSet("MyData", MySch; index=[:f], part_type=MarkAsDeleted) -anon_acset = () -> AnonACSet(MySch; index=[:f]) -anon_acset_bit = () -> AnonACSet(MySch; index=[:f], part_type=MarkAsDeleted) - -data = anon_acset_bit() -add_parts!(data, :B, 5) -add_parts!(data, :A, 5, f = [1,2,3,4,5]) - -undefined_subparts(data, :f) - -rem_parts!(data, :B, 1:3) - -undefined_subparts(data, :f) - -# f=:f -# acs=data_noidx_bit - -# dom_parts(acs,f) - -# acs.subparts[f] -# acs.subparts[f] - -# codom_ids = codom_parts(acs,f) - -# findall([acs.subparts[f][i] ∉ codom_ids for i in dom_parts(acs,f)]) \ No newline at end of file From 0cfc3c8a8dd8459687cac7852bb4a9998e52e32c Mon Sep 17 00:00:00 2001 From: slwu89 Date: Mon, 2 Oct 2023 17:51:05 -0700 Subject: [PATCH 7/9] use parts_type in undefined_subparts --- src/DenseACSets.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DenseACSets.jl b/src/DenseACSets.jl index 1285e4a..b2f659f 100644 --- a/src/DenseACSets.jl +++ b/src/DenseACSets.jl @@ -655,14 +655,14 @@ ACSetInterface.cascading_rem_parts!(acs::ACSet, type, parts) = function ACSetInterface.undefined_subparts(acs::SimpleACSet, f::Symbol) s = acset_schema(acs) f ∈ homs(s; just_names=true) || error("$f is not a hom") - _undefined_subparts(acs, f, acs.parts[dom(s,f)]) + _undefined_subparts(acs, f, parts_type(acs)) end -function _undefined_subparts(acs::SimpleACSet, f::Symbol, ::DenseParts) +function _undefined_subparts(acs::SimpleACSet, f::Symbol, ::Type{<:DenseParts}) findall([!haskey(acs.subparts[f],i) for i in dom_parts(acs,f)]) end -function _undefined_subparts(acs::SimpleACSet, f::Symbol, ::MarkAsDeleted) +function _undefined_subparts(acs::SimpleACSet, f::Symbol, ::Type{<:MarkAsDeleted}) codom_ids = codom_parts(acs,f) findall([acs.subparts[f][i] ∉ codom_ids for i in dom_parts(acs,f)]) end From bd36a0e7e45ae0523115f633e654421f01fd9b6c Mon Sep 17 00:00:00 2001 From: slwu89 Date: Tue, 3 Oct 2023 07:55:02 -0700 Subject: [PATCH 8/9] do not need multiple functions for correct dispatch --- src/DenseACSets.jl | 10 ++-------- test/ACSets.jl | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/DenseACSets.jl b/src/DenseACSets.jl index b2f659f..8488723 100644 --- a/src/DenseACSets.jl +++ b/src/DenseACSets.jl @@ -652,17 +652,11 @@ end ACSetInterface.cascading_rem_parts!(acs::ACSet, type, parts) = delete_subobj!(acs, Dict(type=>parts)) -function ACSetInterface.undefined_subparts(acs::SimpleACSet, f::Symbol) - s = acset_schema(acs) - f ∈ homs(s; just_names=true) || error("$f is not a hom") - _undefined_subparts(acs, f, parts_type(acs)) -end - -function _undefined_subparts(acs::SimpleACSet, f::Symbol, ::Type{<:DenseParts}) +function ACSetInterface.undefined_subparts(acs::SimpleACSet{<:DenseParts}, f::Symbol) findall([!haskey(acs.subparts[f],i) for i in dom_parts(acs,f)]) end -function _undefined_subparts(acs::SimpleACSet, f::Symbol, ::Type{<:MarkAsDeleted}) +function ACSetInterface.undefined_subparts(acs::SimpleACSet{<:MarkAsDeleted}, f::Symbol) codom_ids = codom_parts(acs,f) findall([acs.subparts[f][i] ∉ codom_ids for i in dom_parts(acs,f)]) end diff --git a/test/ACSets.jl b/test/ACSets.jl index 1c6361a..b1ed625 100644 --- a/test/ACSets.jl +++ b/test/ACSets.jl @@ -73,7 +73,7 @@ for dds_maker in dds_makers view(dds,:Φ) isa ColumnView # Deletion. - @test_throws ErrorException undefined_subparts(dds, :X) + @test_throws ArgumentError undefined_subparts(dds, :X) @test undefined_subparts(dds, :Φ) == [] rem_part!(dds, :X, 2) @test undefined_subparts(dds, :Φ) == [1] From 6fe42eb6558834e4c78324b05a5005b6be8d831e Mon Sep 17 00:00:00 2001 From: slwu89 Date: Tue, 3 Oct 2023 15:52:06 -0700 Subject: [PATCH 9/9] test and expand cascading_rem_parts! tests --- test/ACSets.jl | 100 ++++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 39 deletions(-) diff --git a/test/ACSets.jl b/test/ACSets.jl index b1ed625..18301e8 100644 --- a/test/ACSets.jl +++ b/test/ACSets.jl @@ -586,50 +586,74 @@ RecSch = BasicSchema( [],[] ) +# DenseParts @acset_type RecDataInj(RecSch, index=[:src,:tgt], unique_index=[:thing]) @acset_type RecDataIdx(RecSch, index=[:src,:tgt,:thing]) @acset_type RecDataNoIdx(RecSch) -datainj = @acset RecDataInj begin - Thing=3 - Node=3 - Edge=3 - thing=[1,2,3] - src=[1,1,2] - tgt=[1,2,3] -end - -dataidx = @acset RecDataIdx begin - Thing=3 - Node=3 - Edge=3 - thing=[1,2,3] - src=[1,1,2] - tgt=[1,2,3] -end +recdata_makers = [ + RecDataInj, + RecDataIdx, + RecDataNoIdx, + () -> DynamicACSet("RecData", RecSch; index=[:src,:tgt]), + () -> AnonACSet(RecSch; index=[:src,:tgt]) +] -datanoidx = @acset RecDataNoIdx begin - Thing=3 - Node=3 - Edge=3 - thing=[1,2,3] - src=[1,1,2] - tgt=[1,2,3] +for recdata in recdata_makers + mydata = recdata() + add_parts!(mydata, :Node, 3) + add_parts!(mydata, :Thing, 3, thing=[1,2,3]) + add_parts!(mydata, :Edge, 3, src=[1,1,2], tgt=[1,2,3]) + + @test parts_type(mydata) <: DenseParts + + new2old = cascading_rem_parts!(mydata, :Node, 1) + + @test length(new2old[:Thing]) == nparts(mydata,:Thing) + @test nparts(mydata,:Thing) == 2 + @test length(new2old[:Node]) == nparts(mydata,:Node) + @test nparts(mydata,:Node) == 2 + @test length(new2old[:Edge]) == nparts(mydata,:Edge) + @test nparts(mydata,:Edge) == 1 + @test incident(mydata, 3, :thing) == [] + @test incident(mydata, 3, :src) == [] + @test incident(mydata, 3, :tgt) == [] end -map_inj = cascading_rem_parts!(datainj, :Node, 1) -map_idx = cascading_rem_parts!(dataidx, :Node, 1) -map_noidx = cascading_rem_parts!(datanoidx, :Node, 1) - -@test map_inj == map_idx -@test map_idx == map_noidx +# MarkAsDeleted parts +@acset_type RecDataInjMarkDel(RecSch, index=[:src,:tgt], unique_index=[:thing], part_type=BitSetParts) +@acset_type RecDataIdxMarkDel(RecSch, index=[:src,:tgt,:thing], part_type=BitSetParts) +@acset_type RecDataNoIdxMarkDel(RecSch, part_type=BitSetParts) + +recdata_makers = [ + RecDataInjMarkDel, + RecDataIdxMarkDel, + RecDataNoIdxMarkDel, + () -> DynamicACSet("RecData", RecSch; index=[:src,:tgt], part_type=MarkAsDeleted), + () -> AnonACSet(RecSch; index=[:src,:tgt], part_type=MarkAsDeleted) +] -@test nparts(datainj,:Thing) == 2 -@test nparts(datainj,:Node) == 2 -@test nparts(datainj,:Edge) == 1 -@test incident(datainj, 3, :thing) == [] -@test incident(datainj, 3, :src) == [] -@test incident(datainj, 3, :tgt) == [] +for recdata in recdata_makers + mydata = recdata() + add_parts!(mydata, :Node, 3) + add_parts!(mydata, :Thing, 3, thing=[1,2,3]) + add_parts!(mydata, :Edge, 3, src=[1,1,2], tgt=[1,2,3]) + + @test parts_type(mydata) <: MarkAsDeleted + + new2old = cascading_rem_parts!(mydata, :Node, 1) + + @test length(new2old[:Thing]) == nparts(mydata,:Thing) + @test nparts(mydata,:Thing) == 2 + @test length(new2old[:Node]) == nparts(mydata,:Node) + @test nparts(mydata,:Node) == 2 + @test length(new2old[:Edge]) == nparts(mydata,:Edge) + @test nparts(mydata,:Edge) == 1 + # IDs are not updated in MarkAsDeleted, so "1" is the deleted element + @test incident(mydata, 1, :thing) == [] + @test incident(mydata, 1, :src) == [] + @test incident(mydata, 1, :tgt) == [] +end # attributes and an injective index RecAttrSch = BasicSchema( @@ -651,9 +675,7 @@ dataattr = @acset RecAttrData{String,Symbol,Float64} begin attr3=[10.0,11.0,12.0] end -map_attr = cascading_rem_parts!(dataattr, :Node, 1) - -@test map_inj == map_attr +cascading_rem_parts!(dataattr, :Node, 1) @test all(map(x -> x ∈ subpart(dataattr,:attr1), ["2","3"])) @test only(subpart(dataattr,:attr2)) == :c