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

Relational compose #4329

Closed
wants to merge 5 commits into from
Closed

Conversation

stevenganz
Copy link

Related (circuitously) to Issue #4208. Adds the relational_compose operator and updates to work with edge data attributes and to mix graph types.

Steven Ganz added 5 commits November 8, 2020 15:46
…mposition of G and H as relations. Nodes of G; H are the set union of nodes of G and nodes of H. G; H contains an edge from A to C for every combination of an edge in G from A to B and an edge in H from B to C, for any node B. For multigraphs, with keys=True only edges with matching keys are acted upon.
…ompose. This should probably be allowed for other operators as well. Define to_multigraph and use to convert from simple graphs.
@dschult
Copy link
Member

dschult commented Nov 9, 2020

You don't need the to_multigraph methods stuff. Just let the user use H = nx.MultiGraph(G) or similar.

@stevenganz
Copy link
Author

Regarding the formatting, I installed the commit hook (why does it require waiving security checks?) but only after I had put my commits in place. I tried merging them into a different branch, but that didn’t trigger any formatting. The formatting did look fine to me though, and seemed to match the existing style.

Regarding to_multigraph, that isn’t technically necessary, and for that reason is in its an upper commit on its own (and can thus be easily dropped), but does make life much easier for the user to not have to worry about what kind of graph they have. I see no reason not to do use both to_directed and to_multigraph in preprocessing all operator arguments the way I do with relational_compose.

MultiGraph(G) wasn’t working for me. I tried it in testing to_multigraph. I’ll try to reproduce that and open an issue.

graphs = iter(graphs)
C = next(graphs)
for H in graphs:
C = nx.relational_compose(C, H, with_keys)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you make a variant of relational compose such that it does an in-place update on C if possible by setting a kwarg copy=False? This would make this much faster for large numbers of graphs.

Copy link
Author

Choose a reason for hiding this comment

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

I don't see why not. That does sound like it would be useful.

networkx/algorithms/operators/binary.py Show resolved Hide resolved
R.add_nodes_from(H.nodes(data=True))

# add composite edges to result graph
for (gsource, nbrdict) in G.adjacency_iter():
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need a new adjacency_iter method here. You can just do

for gsource, nbrdict in G.adj.items():

Copy link
Author

Choose a reason for hiding this comment

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

OK, thanks. I see that G.adjacency_iter was replaced by G..adjacency, which is no longer supported. I was referring to some old documentation and also there are still stray references to adjacency_iter in the current version. No problem, I'll do it the way you suggest.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, there used to be lots of different ways to do it. Since the the view overhaul there was work on consolidating things such that there was "one true way" to do everything. In this case the .adj attribute has everything you need.

Copy link
Author

Choose a reason for hiding this comment

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

It's best to deprecate and then remove all traces of the previous ways.

Copy link
Member

Choose a reason for hiding this comment

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

Where are the stray references to adjacency_iter? We got rid of that years ago.

Copy link
Author

Choose a reason for hiding this comment

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

Dan, You pointed out the definition of adjacency below, and there are various calls to it. There's an adjacency_iter at examples/subclass/plot_antigraph.py which, although not directly applicable, led me to believe that defining such a function was the appropriate way to handle this.

Copy link
Member

Choose a reason for hiding this comment

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

Thank you! I can believe that we missed that one... I'll open an issue. :}


# add composite edges to result graph
for (gsource, nbrdict) in G.adjacency_iter():
for gtarget in nbrdict.keys():
Copy link
Contributor

Choose a reason for hiding this comment

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

using .keys is superfluous here, but its never bad to be explicit.

# for each edge in H from gtarget to succ_node with the same key as the edge from gsource to gtarget in G, create an edge in R with that key pre-composing the edge from gsource to gtarget in G
for k in succ_nodes[succ_node]:
if k in G[gsource][gtarget]:
R.add_edge(gsource, succ_node, key=k, **(edge_data_combiner(G[gsource][gtarget][k], H[gtarget][succ_node][k]) if with_data and edge_data_combiner else {}))
Copy link
Contributor

Choose a reason for hiding this comment

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

probably best to separate the data dict rectification step into a previous line. It will make errors in edge_data_combiner easier to trace.

Copy link
Author

Choose a reason for hiding this comment

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

Good point.

@@ -355,6 +363,23 @@ def adj(self):
"""
return AdjacencyView(self._adj)

def adjacency_iter(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

not necessary, see above comment

Copy link
Member

Choose a reason for hiding this comment

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

There is already a def adjacency(self): which does this for the Graph classes. ~ line 1370

Copy link
Author

Choose a reason for hiding this comment

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

I see. Am I correct that G.adjacency is last documented in ver. 2.1?

@@ -1,5 +1,6 @@
import pytest
import networkx as nx
from networkx.algorithms.operators.all import relational_compose_all # Why can't this be accessed from nx.relational_compose_all?
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it not exposed in the __init__.py? Is it missing from some __all__ registry?

Copy link
Author

@stevenganz stevenganz Nov 10, 2020

Choose a reason for hiding this comment

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

Ah, was left out of the __all__ registry. Thanks.

Base automatically changed from master to main March 4, 2021 18:20
@dschult dschult added this to the networkx-2.7 milestone Sep 9, 2021
@rossbar rossbar modified the milestones: networkx-2.7, networkx-3.0 Feb 12, 2022
@rossbar
Copy link
Contributor

rossbar commented Jun 28, 2022

This has been stale for quite some time and will likely need significant TLC to get up and running again. Are you still planning to work on this @stevenganz ?

@rossbar rossbar modified the milestones: networkx-3.0, networkx-3.1 Nov 29, 2022
@jarrodmillman jarrodmillman removed this from the 3.2 milestone Jul 20, 2023
@MridulS MridulS closed this Nov 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

6 participants