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

bloq.call_graph() should preserve ordering of successors across calls / build_call_graph should return a Dict instead of Set #845

Closed
tanujkhattar opened this issue Apr 2, 2024 · 7 comments
Assignees
Milestone

Comments

@tanujkhattar
Copy link
Collaborator

Every time you call bloq.call_graph() you can get a different nx.DiGraph where the ordering of successors of a node is different. This happens because build_call_graph returns a Set instead of a Dict so iterating over a set to get the call graph destroys ordering.

I encountered this when writing tests for #732 where the output of get_flame_graph_data is different across calls because the DFS ordering of nodes in bloq.call_graph is different.

@mpharrigan What's the reason to destroy ordering? Is this by design? Can we preserve ordering? I agree that most properties of the call graph analysis shouldn't depend upon the ordering but I think it's still nice to preserve the order across calls.

@mpharrigan
Copy link
Collaborator

Are sets not ordered in Python? either a list of 2-tuples or a dict would be fine. I think the point of the "set" was to encode that order doesn't matter. Perhaps a more important property is that each bloq appears only once, which isn't captured by set.

It's possible that networkx will shuffle things later anyways, so if you want determinism I suggest throwing in some sorteds.

@tanujkhattar
Copy link
Collaborator Author

Are sets not ordered in Python?

Nope. Dicts are, but sets aren't. I vote for a dict instead of a list of 2-tuples.

Perhaps a more important property is that each bloq appears only once, which isn't captured by set.

That's true, and a dict would capture that as well.

It's possible that networkx will shuffle things later anyways

I think it's less likely if we just traverse the graph and not modify it. But we can deal with any potential indeterminism due to networkx when we encounter it. AFAIK, this shouldn't be an issue.

@anurudhp
Copy link
Contributor

anurudhp commented Jun 13, 2024

@mpharrigan should the bloq author ensure that each unique bloq in the BloqCountT occurs only once? i.e. is something like this valid:

counts = set()
if condition_1: counts.add((XGate(), 1))
if condition_2: counts.add((XGate(), 2))
return counts

This luckily works as long as the frequencies are different, but fails if they are equal.

@fdmalone
Copy link
Collaborator

^^^ I've been caught out by this before

@mpharrigan
Copy link
Collaborator

@anurudhp I think that's what this issue is about. If we change it to use dictionaries, you'd have to do something like

counts = defaultdict(lambda: 0)
if condition_1: counts[XGate()] += 1
if condition_2: counts[XGate()] += 2
return counts

@mpharrigan mpharrigan added this to the v1.0 milestone Jul 23, 2024
@mpharrigan
Copy link
Collaborator

My latest thoughts: I think this is still a good idea. IMO, the execution of this change should go through a mini deprecation cycle. Since build_call_graph is not supposed to be called by users directly, we can change its definition to return either a set or a dict; and change the internal uses of the function to turn sets into dictionaries; emit a deprecation warning if a set is encountered; and change all the existing implementations at our leisure to use dictionaries; eventually remove the type annotation for set; and even more eventually, remove the defensive coding within the consumers of build_call_graph.

@dstrain115 dstrain115 assigned dstrain115 and unassigned mpharrigan Aug 27, 2024
dstrain115 added a commit to dstrain115/Qualtran that referenced this issue Sep 9, 2024
- We changed build_call_graph to return a dictionary
as a part quantumlib#845.
- This now emits a deprecation warning now that all the
built-in bloqs are converted.
mpharrigan added a commit that referenced this issue Sep 9, 2024
* Add warning for build_call_graph returning a set

- We changed build_call_graph to return a dictionary
as a part #845.
- This now emits a deprecation warning now that all the
built-in bloqs are converted.

* Add DeprecationWarning

---------

Co-authored-by: Matthew Harrigan <[email protected]>
@mpharrigan
Copy link
Collaborator

This is done thanks to @dstrain115

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

No branches or pull requests

5 participants