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

Throw error when length of sequence defining node / edge attributes do not match the number of nodes / edges added #715

Open
lubin-liu opened this issue Sep 26, 2023 · 1 comment

Comments

@lubin-liu
Copy link

What is the feature or improvement you would like to see?
Currently, if the number of nodes / edges do not match the length of the list defining an attribute during graph initialization or add_vertices / add_edges, the list is truncated or propagated. I think throwing an error when the length of the list defining the attributes do not match the number of nodes / edges being imported would be helpful. This would also be consistent with the documentation for methods that has an attribute parameter:

the attributes of the vertices as a dictionary. The keys of the dictionary must be the names of the attributes; the values must be iterables with exactly n items where n is the number of vertices.
the attributes of the edges as a dictionary. The keys of the dictionary must be the names of the attributes; the values must be iterables with exactly m items where m is the number of edges.

dict of sequences, all of length equal to the number of vertices to be added, containing the attributes of the new vertices. If n is a string (so a single vertex is added), then the values of this dict are the attributes themselves, but if n=1 then they have to be lists of length 1

dict of sequences, all of length equal to the number of edges to be added, containing the attributes of the new edges.

Sample below for current behaviour:

import igraph as ig

g = ig.Graph()
g.add_vertices(3, attributes={'weight' : [1,2], 'name' : ['a']})
list(g.vs)
[igraph.Vertex(<igraph.Graph object at 0x7890c1d6d040>, 0, {'weight': 1, 'name': 'a'}),
 igraph.Vertex(<igraph.Graph object at 0x7890c1d6d040>, 1, {'weight': 2, 'name': 'a'}),
 igraph.Vertex(<igraph.Graph object at 0x7890c1d6d040>, 2, {'weight': 1, 'name': 'a'})]

Use cases for the feature
Explain when and for what purpose the feature would be useful.

To help avoid silent bugs due to API silently propagating or truncating attributes when adding nodes / edges.

@ntamas
Copy link
Member

ntamas commented Oct 3, 2023

Thanks for the suggestion. Unfortunately this would be an API-breaking change and I'm afraid that there is code out there that relies on this behaviour.

Behind the scenes, all the examples you mentioned boil down to a call to g.vs[attr_name] = value or g.es[attr_name] = value. I've made a questionable design decision in the past where I imitated R's behaviour of "recycling" values in a vector when the vector is shorter than the vector it is being assigned to. Essentially, we are doing this when value is a sequence:

from itertools import cycle
g.vs[attr_name] = cycle(value)

This allows one to set attributes conveniently when the graph has some kind of periodicity, e.g.:

g.vs["type"] = [True, False]

would create a bipartite graph where odd and even-numbered nodes belong to different groups.

When I made this decision >10 years ago, igraph's R and Python interface evolved together and there were many features that I "borrowed" from the R interface to make the Python interface more familiar to users who were switching from the R interface. If I were to decide today, I would not implement the recycling behaviour and throw an exception instead, as you proposed (since the recycling behaviour is easy to replicate with cycle).

Right now the only way I see to move ahead is to deprecate this behaviour in the next version with a DeprecationWarning, and then remove the feature in some later version. Unfortunately, these warnings are off by default so the visibility of such a warning is questionable.

I'll keep the issue open for the time being so others can add their opinion if needed, but I am not planning to make changes now.

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

No branches or pull requests

2 participants