Browse Source

BUG: Handle degenerate case of conjunctive query with no output ports.

These are effectively counting queries.
pull/421/head
Evan Patterson 2 weeks ago
parent
commit
7f60702330
  1. 4
      benchmark/Graphs.jl
  2. 24
      src/wiring_diagrams/Algebras.jl
  3. 6
      test/wiring_diagrams/Algebras.jl

4
benchmark/Graphs.jl

@ -83,9 +83,9 @@ function ntriangles(g::T, ::TriangleHomomorphism) where T
count
end
function ntriangles(g, ::TriangleQuery)
length(query(g, triangle_query))
length(query(g, ntriangles_query))
end
const triangle_query = @relation (v1=v1, v2=v2, v3=v3) begin
const ntriangles_query = @relation (;) begin
E(src=v1, tgt=v2)
E(src=v2, tgt=v3)
E(src=v1, tgt=v3)

24
src/wiring_diagrams/Algebras.jl

@ -127,15 +127,19 @@ end
""" Evaluate a conjunctive query on an attributed C-set.
The query is a undirected wiring diagram whose boxes and ports are assumed to be
named through attributes `:name` and `:port_name`/`:outer_port_name`. To define
such a diagram, use the named form of the [`@relation`](@ref) macro.
The query is a undirected wiring diagram (UWD) whose boxes and ports are assumed
to be named through attributes `:name` and `:port_name`/`:outer_port_name`. To
define such a diagram, use the named form of the [`@relation`](@ref) macro.
This function straightforwardly wraps the [`oapply`](@ref) method for
multispans, which implements the UWD algebra of multispans.
The result is a table, by default a `TypedTable`, whose columns correspond to
the outer ports of the UWD. If the UWD has no outer ports, the query is a
counting query and the result is a vector whose length is the number of results.
For its implementation, this function wraps the [`oapply`](@ref) method for
multispans, which defines the UWD algebra of multispans.
"""
function query(X::AbstractACSet, diagram::UndirectedWiringDiagram,
params=NamedTuple(); table_type::Type=TypedTables.Table)
params=(;); table_type::Type=TypedTables.Table)
# For each box in the diagram, extract span from ACSet.
spans = map(boxes(diagram), subpart(diagram, :name)) do b, name
apex = FinSet(nparts(X, name))
@ -159,8 +163,12 @@ function query(X::AbstractACSet, diagram::UndirectedWiringDiagram,
# Call `oapply` and make a table out of the resulting span.
outer_names = subpart(diagram, :outer_port_name)
outer_span = oapply(diagram, spans, Ob=SetOb, Hom=FinDomFunction{Int})
table = NamedTuple{Tuple(outer_names)}(Tuple(map(collect, outer_span)))
make_table(table_type, table)
if isempty(outer_names)
fill((;), length(apex(outer_span)))
else
table = NamedTuple{Tuple(outer_names)}(Tuple(map(collect, outer_span)))
make_table(table_type, table)
end
end
end

6
test/wiring_diagrams/Algebras.jl

@ -62,6 +62,10 @@ paths2 = @relation (start=start, stop=stop) begin
E(src=start, tgt=mid)
E(src=mid, tgt=stop)
end
count_paths2 = @relation (;) begin
E(src=start, tgt=mid)
E(src=mid, tgt=stop)
end
# Graph underlying a commutative squares.
square = Graph(4)
@ -75,11 +79,13 @@ add_vertices!(squares2, 2)
add_edges!(squares2, [2,4,5], [5,6,6])
result = query(squares2, paths2)
@test tuples(columns(result)...) == [(1,4), (1,4), (1,5), (2,6), (2,6), (3,6)]
@test length(query(squares2, count_paths2)) == 6
result = query(squares2, paths2, (start=1,))
@test tuples(columns(result)...) == [(1,4), (1,4), (1,5)]
result = query(squares2, paths2, (start=1, stop=4))
@test result == Table((start=[1,1], stop=[4,4]))
@test length(query(squares2, count_paths2, (start=1, stop=4))) == 2
cycles3 = @relation (edge1=e, edge2=f, edge3=g) where (e,f,g,u,v,w) begin
E(_id=e, src=u, tgt=v)

Loading…
Cancel
Save