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

trophic_levels now checks for paths from each node to a basal node #7453

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

Conversation

Aditya-Shandilya1182
Copy link
Contributor

@Aditya-Shandilya1182 Aditya-Shandilya1182 commented May 20, 2024

Fixes #6899

@Aditya-Shandilya1182
Copy link
Contributor Author

I added the function bfs_reachable_from_basal to perform BFS and determine nodes reachable from basal nodes.

  • Initialized visited and reachable_nodes sets to track visited nodes and reachable nodes respectively.
  • Iterated over basal nodes and used BFS to explore all reachable nodes, adding them to the reachable_nodes set.
  • Raised nx.NetworkXError if no basal nodes are present, indicating that trophic levels are not defined.
  • Checked if all nodes in the graph are reachable from the basal nodes, raising nx.NetworkXError if not.

Following code was used to check the proper functioning of the feature.

edges = [(0, 5), (0, 3), (0, 33), (3, 2), (3, 24), (3, 32), (33, 1), (33, 10), (2, 3), (2, 16), (1, 33), (10, 16), (16, 4), (16, 9), (18, 11), (11, 5), (11, 21), (4, 2), (4, 33), (9, 16), (9, 26), (9, 17), (26, 19), (17, 10), (19, 10), (19, 9), (19, 7), (19, 0)]
G = nx.DiGraph(edges)
res = nx.trophic_levels(G)
print(res[0])

Result before changes:

inf

Result after changes:

infERR

@Aditya-Shandilya1182
Copy link
Contributor Author

This code is written to address issue #6899.

Copy link
Member

@dschult dschult left a comment

Choose a reason for hiding this comment

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

Thanks for this!
I think the bulk of this could call the existing nx.bfs_layers function which takes a parameter for multiple source nodes.

See below.

networkx/algorithms/centrality/trophic.py Outdated Show resolved Hide resolved
networkx/algorithms/centrality/trophic.py Outdated Show resolved Hide resolved
networkx/algorithms/centrality/trophic.py Outdated Show resolved Hide resolved
Copy link
Contributor

@rossbar rossbar left a comment

Choose a reason for hiding this comment

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

At first glance this seems to be on the right track, thanks! This should also have some test cases to demonstrate the changed/fixed behavior in trophic_levels!

Comment on lines 45 to 49
reachable_nodes = {
node
for layer in nx.bfs_layers(graph, sources=basal_nodes)
for node in layer
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd vote to use this directly on L59 and do away with the extra function definition - eliminating indirection makes the code much easier to follow IMO!

@Aditya-Shandilya1182
Copy link
Contributor Author

Aditya-Shandilya1182 commented May 21, 2024

I will try to add the test cases.

@dschult
Copy link
Member

dschult commented May 23, 2024

I include a comment with the term

Fixes #6899

so that merging this PR automatically closes that issue.
More on linking a Pr to an Issue
[Edit: -- oops! that phrase has to be in the original post. I added it there so they are connected.]

@dschult dschult changed the title Added function to check path from bassal node trophic_levels now checks for paths from each node to a basal node May 23, 2024
@dschult
Copy link
Member

dschult commented May 23, 2024

I think the tests actually passed -- it was a red X because one test got canceled, but rerunning it allowed it to pass.

A second test could be a graph that works plus an isolated node. That will trigger the other exception added in this PR.

@eriknw
Copy link
Contributor

eriknw commented May 23, 2024

This looks like a reasonable approach. The latest dev version of np.linalg.inv says this:

If a is detected to be singular, a LinAlgError is raised. If a is ill-conditioned, a LinAlgError may or may not be raised, and results may be inaccurate due to floating-point errors.

Should a more clear error message be given for the null graph? nx.trophic_levels(nx.DiGraph()) currently raises NetworkXError: Graph has no nodes or edges

@Aditya-Shandilya1182
Copy link
Contributor Author

I think the tests actually passed -- it was a red X because one test got canceled, but rerunning it allowed it to pass.

A second test could be a graph that works plus an isolated node. That will trigger the other exception added in this PR.

Are you referring to the test case I added and then removed?

@dschult
Copy link
Member

dschult commented May 24, 2024

Yes -- I was referring to the test added and then removed. That tested the "no basal nodes" exception.

@Aditya-Shandilya1182
Copy link
Contributor Author

Should I add it again then?

@dschult
Copy link
Member

dschult commented May 24, 2024

Yes -- could you add it again, and a test for a network that should work, but with an added isolated node so that it doesn't work -- and raises an exception from the 2nd code-check. Does this make sense?

@Aditya-Shandilya1182
Copy link
Contributor Author

I tried adding a test for isolated nodes. But the test failed. Should I add a condition to handle isolated nodes? Or is there something I am missing here?

Test:

def test_trophic_levels_with_isolated_node():
    G = nx.DiGraph()
    # Adding edges to create a graph with a basal node
    edges = [(0, 1), (1, 2), (2, 3)]
    G.add_edges_from(edges)
    
    # Adding an isolated node
    G.add_node(4)
    print(G.nodes)
    
    with pytest.raises(nx.NetworkXError):
        nx.trophic_levels(G)

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.

"nx.trophic_levels" returning strange INF value caused by insufficient checking for singular matrix
4 participants