Skip to content
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

Higher level incident call #60

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Higher level incident call #60

wants to merge 4 commits into from

Conversation

GeorgeR227
Copy link
Contributor

This PR adds a higher level collected_incident function that is meant to serve as a replacement to the many reduce-vcats we tend to use when trying to call incident on multiple things at once. Since results from this function are always combined into a single vector of unique results, as opposed to incident which may return a vector of vector of results, care must be taken when calling this function into different tables or when calling with multiple inputs.

This function is meant to be generic to work well with the idea that DiagrammaticEquations should have abstracted algorithms but I've also added specific helper functions for Decapodes that may be useful.

Added graph examples with more complicated uses
These functions are meant as basic decapodes querying functions
@lukem12345
Copy link
Member

Some calls may be better off as @generated functions. We should talk about what it would take for this to be in ACSets main at Wednesday's Catlab Developer's meeting.

@GeorgeR227
Copy link
Contributor Author

I'd rather not be writing @generated calls since we've seen that they don't have their intended effects in ACSets anyway and that'd severely complicate the code.

Having this in ACSets main sounds fine but it leads me to wonder what exactly is supposed to be the difference between ACSets and DiagrammaticEquations.

@lukem12345
Copy link
Member

To ACSets.jl belong data structures and algorithms over generic (not only compute-graph like) schemas. Partitioning the code as of the most recent commit, src/query.jl and test/query.jl are ACSets.jl-like.

The "query" related code is quite similar to the chained-subparts code, which Sean contributed to ACSets.jl, in that case using CompTime. A recent draft PR demonstrates how using @generated to replace that feature allows the Julia compiler to e.g. eliminate intermediate allocations from certain loops.

Sean's PR provides syntactic sugar for nested calls to incident. This current PR for adjacent. The code written for the current PR can only be improved by consulting with those sister ones.

The array/append! method before would always return Vector{Any}, which didn't match incident's behavior.
Copy link

codecov bot commented Aug 8, 2024

Codecov Report

Attention: Patch coverage is 80.00000% with 6 lines in your changes missing coverage. Please review.

Project coverage is 86.55%. Comparing base (55d2972) to head (e54b692).

Files Patch % Lines
src/deca/deca_query.jl 40.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #60      +/-   ##
==========================================
- Coverage   86.80%   86.55%   -0.25%     
==========================================
  Files          13       15       +2     
  Lines         894      922      +28     
==========================================
+ Hits          776      798      +22     
- Misses        118      124       +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@jpfairbanks jpfairbanks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GeorgeR227, could we replace some of this with calls to querry from Catlab?

https://github.com/AlgebraicJulia/Catlab.jl/blob/d336c7bb6b2f7b7e0e105553918c4caccdd99d6f/src/wiring_diagrams/Algebras.jl#L158

It lets you use the relation macro as a declarative DSL for queries.

Since most queries are a chain of subpart and incident calls, you just write those as simple relations.

If you want to find all the variables that are computed by a direct circularity.

q = @relation begin
  Op1(src=v, tgt=u)
  Op1(src=u, tgy=v)
end
d = SummationDecapode(...)
query(d, q)

This would match patterns like u = f(v); v = g(u). But then you can also do complex patterns like:

@relation begin
  Op1(src=v, tgt=u)
  Op2(proj1=v, proj2=u, res=x)
end

This is a pattern of a triangular dependency where what looks like an op2 on v,u is actually a unary operation on v, because u is derived from v.

u = f(v)
x = g(v,u)

return !isempty(collected_incident(d, var, [:src, :proj1, :proj2, :summand]))
end

function get_variable_parents(d::SummationDecapode, var::Int)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we rename all these java getters to remove get_


function collected_incident(d::ACSet, searches::AbstractVector, args...)

isempty(searches) && error("Cannot have an empty search")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't empty search return empty list?


export collected_incident

function collected_incident(d::ACSet, searches::AbstractVector, args...)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring on exported function


function collected_incident(d::ACSet, search, lookup_array)
numof_channels = length(lookup_array)
empty_outputchannels = fill(nothing, numof_channels)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't this an array of nothings? You can't push something into these "channels"

end


function collected_incident(d::ACSet, search, lookup_array, output_array)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the type of search?


function collected_incident(d::ACSet, search, lookup_array, output_array)
length(lookup_array) == length(output_array) || error("Input and output channels are different lengths")
isempty(lookup_array) && error("Cannot have an empty lookup")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should empty lookup_array return an empty list? empty search => empty results makes sense to me.

index_result = incident(d, search, lookup)
isnothing(output_channel) ? index_result : d[index_result, output_channel]
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file feels over engineered for something simple, but I can't tell what it is supposed to do because of the lack of docstrings.

sort(test) == sort(expected)
end

get_index_from_name(d::SummationDecapode, varname::Symbol) = only(incident(d, varname, :name))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no java please. just call this index rely on dispatch to use the name because you gave it a symbol.

using ACSets

function array_contains_same(test, expected)
sort(test) == sort(expected)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so you want to handle multiplicity? Could replace with setequal(a,b) = Set(a) == Set(b)

end

function get_variable_parents(d::SummationDecapode, var::Int)
return collected_incident(d, var, [:tgt, :res, :res, [:summation, :sum]], [:src, :proj1, :proj2, :summand])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea what this is supposed to do, is this supposed to be a conjucnction of disjunctions type query?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants