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

deterministic shuffling #190

Merged
merged 1 commit into from
Feb 28, 2022
Merged

deterministic shuffling #190

merged 1 commit into from
Feb 28, 2022

Conversation

Fil
Copy link
Member

@Fil Fil commented Feb 28, 2022

fixes #189
note: shuffling is here to increase performance (#83)

@jessihamel

fixes #189
note: shuffling is here to increase performance (#83)
@Fil Fil requested a review from mbostock February 28, 2022 10:46
@Fil Fil merged commit 9e0ac43 into main Feb 28, 2022
@Fil Fil deleted the fil/deterministic-pack branch February 28, 2022 14:58
@mbostock
Copy link
Member

mbostock commented Apr 1, 2022

I think it might have been better to initialize the LCG in d3.pack rather than d3.packEnclose, or at least to support the option of passing in a seed so that the randomness is configurable. (Or, a way to disable the shuffling, and require the caller to do the shuffling instead.) This PR re-initializes the LCG each time d3.packEnclose is invoked, which happens many times during d3.pack.

Also, I’m kinda confused that d3.packEnclose returns different results based on shuffling, but I imagine it might be possible if there are multiple enclosing circles that are exactly or almost exactly the same size?

@mbostock
Copy link
Member

mbostock commented Apr 1, 2022

And actually, I don’t think this PR affected the determinism of d3.pack? Because this PR changed the behavior of d3.packEnclose, but that’s not used by d3.pack—we use an internal method that doesn’t do shuffling.

Edit: Wait, no, it does use the shuffle, here:

a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a);

It’s just really confusing because we have two functions called “packEnclose” that do different things. 🤦

export function packEnclose(circles) {

Fil added a commit that referenced this pull request Apr 1, 2022
@Fil Fil mentioned this pull request Apr 1, 2022
@Fil
Copy link
Member Author

Fil commented Apr 1, 2022

pack calls packChildren which calls packEnclose; the unit test is the case mentioned in #189, where the result would be unpredictable—it uses d3.pack, and fails (sometimes) if you replace lcg by Math.random.

The shuffling is here just to improve performance (as you explained in #83), so I don't think it needs to be configurable.

For the problem of repeated lcg instanciation: we want all calls to packEnclose to be deterministic; maybe a solution is to inline the implementation: #192

@mbostock mbostock mentioned this pull request Apr 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Suggestion: pack() layouts with deterministic outputs
2 participants