-
Notifications
You must be signed in to change notification settings - Fork 4
[PartitionedGraphs] Small changes #114
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
base: main
Are you sure you want to change the base?
Conversation
- `vertices(::QuotientView)` now directly returns the keys `paritioned_vertices` return value. - `edges(::QuotientView)` now directly returns the edges of the `quotient_graph` return value (to coincide with interface overloading priority) - Converting a `QuotientView` to graph now calls `quotient_graph` directly - Adding methods for return directed/undirected graph types. Fix imports Fix rebase
This behaves similarly to `partitionedgraph` function.
…ype by default This function can now be used `SimpleGraph` etc without promoting to `NamedGraph`.
This function constructs a graph with no edges, but with vertices of the quotient graph.
… depending on graph type.
…eating quotient graph
…ype as a parameter Allows for more generic quotient graph types.
…s for `PartitionedGraph`
…methods for `AbstractSimpleGraph`.
- argument `vertices` must be of type `Base.OneTo{Int}`.
…e, and triple argument methods. This interface is to overload `similar_graph(graph)`, i.e. the single argument method.
This function now acts similarly to `similar_graph`.
Co-authored-by: Matt Fishman <[email protected]>
The function `to_graph_indexing` now dispatches to `to_graph_indices` for type of `AbstractGraphIndices` and `to_graph_index` otherwise.
…stic about the iterables they take Previous behaviour was to accept `Vertices`/`Edges` only.
…sed on `eltype` of `vertices` argument, if provided.
On this point, somewhere this could be problematic is if In [19]: g = NamedGraph([1.0, 1.5, 2.0])
NamedGraph{Float64} with 3 vertices:
3-element NamedGraphs.OrderedDictionaries.OrderedIndices{Float64}:
1.0
1.5
2.0
and 0 edge(s):
NamedEdge{Float64}[]
In [20]: similar_graph(g, [1, 2]) # use integer literals out of laziness
NamedGraph{Int64} with 2 vertices:
2-element NamedGraphs.OrderedDictionaries.OrderedIndices{Int64}:
1
2
and 0 edge(s):
NamedEdge{Int64}[]
In [21]: similar_graph(g, Any[1, 1.5]) # accidentally `eltype==any` due to type instability somewhere
NamedGraph{Any} with 2 vertices:
2-element NamedGraphs.OrderedDictionaries.OrderedIndices{Any}:
1
1.5
and 0 edge(s):
NamedEdge{Any}[]One ends up with graphs with h = similar_graph(g)
add_vertices!(h, ...)to make sure I have made changes to |
|
It's a good point, I was wondering about that as well. I would lean towards taking the input literally for now and leave it up to users to input vertices with the intended element/vertex type, and we could circle back to that if it seems to cause problems. |
…nt vertices and edges.
|
@jack-dunham I had forgetten, but |
…bject when iterating.
…ype constructor for `QuotientVertices`.
| end | ||
| end | ||
|
|
||
| quotients(qvs::QuotientVertexVertices) = getfield(qvs, :quotients) |
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.
I think this is a case where it would be better to not define this function and instead directly use qvs.quotients, to make it clearer this is just accessing data in the struct and not really a generic function.
| function QuotientEdges{V, E}(edges::Es) where {V, E, Es} | ||
| @assert E <: eltype(Es) | ||
| return new{V, E, Es}(edges) | ||
| end |
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.
Related to offline discussions, I think we should remove this constructor and just get the edge type from the input (we can revisit if use cases arise that don't have reasonable alternatives).
| function Base.iterate(qes::QuotientEdges, state = nothing) | ||
| if isnothing(state) | ||
| out = iterate(qes.edges) | ||
| else | ||
| out = iterate(qes.edges, state) | ||
| end | ||
| if isnothing(out) | ||
| return nothing | ||
| else | ||
| (v, s) = out | ||
| return (QuotientEdge(v), s) | ||
| end | ||
| end |
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.
The iterate definitions seem a bit complicated to me. It looks like they are all basically a lazy map over iterating over one of the fields. It seems like that can be implemented more simply like this:
struct Wrapper{T}
data::T
end
Base.length(w::Wrapper) = length(w.data)
Base.eltype(w::Wrapper) = String # Maybe use `Base.promote_op` if the map is more complicated?
function Base.iterate(w::Wrapper, state...)
return iterate(Iterators.map(string, w.data), state...)
endwhich enables:
julia> x = Wrapper([1, 2, 3])
Wrapper{Vector{Int64}}([1, 2, 3])
julia> collect(x)
3-element Vector{String}:
"1"
"2"
"3"
I think then we wouldn't need iterate_graph_indices.
| end | ||
| end | ||
|
|
||
| quotients(qes::QuotientEdgeEdges) = getfield(qes, :quotients) |
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.
Is this function needed? Could we just use direct field access?
| Vertices(vertices::Vs) where {Vs} = new{eltype(Vs), Vs}(vertices) | ||
| end | ||
|
|
||
| Vertices(v1, v2, vertices...) = Vertices(vcat([v1, v2], collect(vertices))) |
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.
I'm not a fan of this constructor, I think we should keep constructors simpler and stricter, for example just have one kind of expected input (in this case, only accept a single collection of vertices). Wouldn't this kind of use case already be handled by the basic constructor, and you can pass a Tuple of vertices, i.e. Vertices(("a", "b", "c"))?
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.
As a concrete issue with this constructor, it makes Vertices(["a"]) ambiguous, since it isn't clear if that is supposed to be the set of vertices, or just the length-1 case of passing multiple arguments (which then if I understand this constructor, would interpret ["a"] as a vertex itself). So it is better to just avoid that kind of ambiguity and keep constructors stricter.
| end | ||
| end | ||
|
|
||
| Edges(e1, e2, edges...) = Edges(vcat([e1, e2], collect(edges))) |
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.
Same comment as above.
| Base.iterate(gi::AbstractGraphIndices, state = nothing) = iterate_graph_indices(identity, gi, state) | ||
| function iterate_graph_indices(f, gi::AbstractGraphIndices, state) | ||
| if isnothing(state) | ||
| out = iterate(parent_graph_indices(gi)) | ||
| else | ||
| out = iterate(parent_graph_indices(gi), state) | ||
| end | ||
| if isnothing(out) | ||
| return nothing | ||
| else | ||
| (v, s) = out | ||
| return (f(v), s) | ||
| end | ||
| end |
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.
Same comment as above regarding a simpler iterate definition.
| function Base.iterate(qvs::QuotientVertices, state = nothing) | ||
| return NamedGraphs.iterate_graph_indices(QuotientVertex, qvs, state) | ||
| end |
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.
Same comment as above regarding a simpler iterate definition.
| function Base.iterate(qvs::QuotientVertexVertices, state = nothing) | ||
| return NamedGraphs.iterate_graph_indices(v -> quotient_index(qvs)[v], qvs, state) | ||
| end |
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.
Same comment as above regarding a simpler iterate definition.
| end | ||
| end | ||
|
|
||
| QuotientVertices(vertices...) = QuotientVertices(collect(vertices)) |
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.
Same comment as the ones for the analogous Vertices and Edges constructors.
This PR includes the following changes to [PartitionedGraphs]
NamedGraphsinterface functions to various data types.QuotientViewnow directly callsquotient_graph.edgesandverticesonQuotientViewnow returns according to the interface priority.QuotientViewsofAbstractSimpleGraphswill now return a graph of similar type.