-
Notifications
You must be signed in to change notification settings - Fork 77
Added a change-log: new file, v1.0.0_changelog.md #467
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
Changes from 5 commits
e4efc64
64f4892
5f69be0
b27717a
6d490e1
ac7ac74
53e1e47
e7e03f6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we change this file name to "CHANGELOG.md". When that is finished, we can add it to the documentation by
```{include} ../../CHANGELOG.md
```{toctree} topics/v1p0p0_migration_guide ```{toctree} topics/changelog
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am inclined to let you do this, because I am not confident that I know how to configure the docs correctly. On the one hand, how hard could it be, but on the other hand, it looks to be trivial for someone who knows how to do it, so why take the chance of screwing up? So, I am planning to leave the current file as-is, and let you rename it in git and put it where you want and then update the docs tables of contents, etc. Also TBD is to add the actual links in the change-log to other documentation. I have flagged each place where a link is needed with my standard: frm: TODO: prefix. In short, I am assuming that it would take you longer to explain to me what I need to do than it would take you to just do it. If that is not correct, then just tell me to not be a scaredy-cat and to just do it...
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's no problem; I'm happy to do all of this. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,344 @@ | ||
| ## [v1.0.0] - August 2026 | ||
|
|
||
| ### Added | ||
|
chief-dweeb marked this conversation as resolved.
|
||
|
|
||
| #### Markov chains (module: chain) | ||
| * Added ability to incrementally configure the chain. | ||
|
|
||
| You can explicitly set class attributes, such as: `chain.initial_partition = ...`. | ||
|
|
||
| Functions to add constraints and updaters: | ||
|
|
||
| * add_constraint() | ||
| * add_constraints() | ||
| * add_updater() | ||
| * add_updaters() | ||
|
|
||
| Function to check whether a chain is fully configured: | ||
|
|
||
| * check_valid() | ||
|
|
||
| #### Graphs (module: graph) | ||
| * Added methods to query and access the embedded NetworkX/RustworkX graph. | ||
|
|
||
| * is_nx_graph() | ||
| * is_rx_graph() | ||
| * get_nx_graph() | ||
| * get_rx_graph() | ||
|
|
||
| * Added methods for converting between GerryChain, NetworkX, and RustworkX graphs, and to create an empty graph. | ||
|
|
||
| * from_networkx() | ||
| * from_rustworkx() | ||
| * from_null_networkx() | ||
| * to_networkx_graph() | ||
|
|
||
|
|
||
| * Added methods to translate node_ids between NetworkX and RustworkX and between parent graphs and subgraphs - to deal with the differences between the way NetworkX and RustworkX implement node_ids. | ||
|
|
||
| * original_nx_node_id_for_internal_node_id() | ||
| * internal_node_id_for_original_nx_node_id() | ||
| * get_nx_to_rx_node_id_map() | ||
| * translate_subgraph_node_ids_for_set_of_nodes() | ||
| * original_nx_node_ids_for_list() | ||
| * original_nx_node_ids_for_set() | ||
| * translate_subgraph_node_ids_for_flips() | ||
|
|
||
| * Added methods to handle the fact that in RustworkX, edges are different from edge_ids. In both NetworkX and RustworkX, an edge is a tuple of node_ids. In NetworkX, there is no difference between an edge and an edge_id, but in RustworkX an edge_id is an integer. | ||
|
|
||
| * get_edge_id_from_edge() | ||
| * get_edge_from_edge_id() | ||
|
|
||
| #### Proposals (module: proposals) | ||
|
|
||
| * Added new names for legacy functions. The new names adhere to the naming convention for creating proposal functions, "build_xxx_proposal_fn". Note that the legacy functions continue to exist. | ||
|
|
||
| * build_any_node_flip_proposal_fn() == propose_any_node_flip() | ||
| * build_random_flip_proposal_fn() == propose_random_flip() | ||
| * build_flip_every_district_proposal_fn() == propose_flip_every_district() | ||
| * build_chunk_flip_proposal_fn() == propose_chunk_flip() | ||
| * build_slow_reversible_proposal_fn() == slow_reversible_propose() | ||
| * build_slow_reversible_bi_proposal_fn() == slow_reversible_propose_bi() | ||
|
|
||
| #### ReCom proposals (module: proposals) | ||
| * Changed the ReCom class to be a namespace that defines the five variants of recom that were discussed in the article, "Spanning Tree Methods for Sampling Graph Partitions": | ||
|
|
||
| * A = cut_edges_mst() | ||
| * B = district_pairs_mst() | ||
| * C = cut_edges_ust() | ||
| * D = district_pairs_ust() | ||
| * R = reversible() | ||
|
|
||
| * Added convenience functions to create recom proposal functions: | ||
|
|
||
| * build_recom_proposal_fn() | ||
| * build_reversible_recom_proposal_fn() | ||
|
|
||
| #### Multi-member ReCom (module: proposals) | ||
|
|
||
| * Added functions and the MultiMemberReCom class to support multi-member ReCom. These new functions and the MultiMemberReCom class mirror the routines and class for standard ReCom: | ||
|
|
||
| * multi_member_recom() | ||
| * build_multi_member_recom_proposal_fn() | ||
| * epsilon_tree_bipartition_multi_member() | ||
| * class MultiMemberReCom | ||
| * cut_edges_mst() | ||
| * district_pairs_mst() | ||
| * cut_edges_ust() | ||
| * district_pairs_ust() | ||
|
|
||
| #### Constraints for multi-member ReCom (module: constraints) | ||
|
|
||
| * Added a new constraint to support multi-member ReCom | ||
|
|
||
| * within_percent_of_ideal_population_per_member() | ||
|
|
||
| ### Changed | ||
|
|
||
| #### Graphs | ||
|
|
||
| * `GerryChain.Graph` no longer subclasses `networkx.Graph`. Node and edge data access has changed. See the v1.0 migration guide. [link-name](https://ibm.com) | ||
|
|
||
| frm: TODO: Add link to the v1.0 migration guide. | ||
|
|
||
| * Changed the way to access node and edge data | ||
|
|
||
| * To access node data, use: my_graph.node_data(...node_id...) | ||
| * To access edge data, use: my_graph.edge_data(...edge_id...) | ||
|
|
||
| * GerryChain now uses independent random number generators configured through parameters, rng= . See the reproducibility guide. [link-name](https://ibm.com) | ||
|
|
||
| frm: TODO: add link to reproducibility guide | ||
|
|
||
| #### Changes to function names: | ||
|
|
||
| * In module constraints: | ||
|
|
||
| * L1_polsby_popper() renamed to be: L_1_polsby_popper() | ||
| * L1_reciprocal_polsby_popper() renamed to be: L_1_reciprocal_polsby_popper() | ||
|
chief-dweeb marked this conversation as resolved.
Outdated
|
||
|
|
||
| * In module grid: | ||
|
|
||
| * create_grid_graph() renamed to be: create_grid_nx_graph() | ||
|
|
||
| #### Changes to names for function parameters | ||
|
|
||
| * GerryChain has adopted the convention that the names of parameters that are themselves function will end in "_fn". | ||
|
|
||
| ### Removed | ||
|
chief-dweeb marked this conversation as resolved.
Outdated
|
||
| #### ? | ||
| #### ? | ||
|
|
||
|
chief-dweeb marked this conversation as resolved.
Outdated
|
||
| # DELETE EVERYTHING BELOW HERE | ||
| After checking with Peter | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good to go after addressing above comments. |
||
|
|
||
| ## Internal functions - not included in changelog... | ||
|
|
||
| 📄 [ADDED FILE] _config.py | ||
|
|
||
| 📄 [ADDED FILE] _rng.py | ||
|
|
||
| 📄 [REMOVED FILE] _version.py | ||
|
|
||
| 📝 File: chain.py | ||
|
|
||
| 🔹 [Class MarkovChain] ADDED function: __lock(self) | ||
|
|
||
| 🔹 [Class MarkovChain] ADDED function: __run(self, proposal_fn, total_steps, initial_partition) | ||
|
|
||
| 🔹 [Class MarkovChain] ADDED function: __setattr__(self, name, value) | ||
|
|
||
| 🔹 [Class MarkovChain] ADDED function: __unlock(self) | ||
|
|
||
| 🔸 [Class MarkovChain] REMOVED function: __next__ | ||
|
|
||
| 📝 File: graph/graph.py | ||
|
|
||
| 🔹 [Global] ADDED function: _add_boundary_perimeters_to_nx_graph(nx_graph, geometries) | ||
| 🔸 [Global] REMOVED function: add_boundary_perimeters | ||
|
|
||
|
|
||
| 🔹 [ADDED CLASS] _GeoInterface | ||
|
|
||
| 🔹 [Class Graph] ADDED function: __iter__(self) | ||
|
|
||
| 📝 File: proposals/tree_proposals.py | ||
|
|
||
| 🔸 [Class ReCom] REMOVED function: __call__ | ||
|
|
||
| 📝 File: updaters/election.py | ||
|
|
||
| ⚠️ [Class Election] SIGNATURE CHANGED: __call__ | ||
| Old: (self) | ||
| New: (self, partition) | ||
|
|
||
| 📄 [ADDED FILE] examples/__init__.py | ||
|
|
||
| ## Stuff that I think should not be included: | ||
|
|
||
| 📝 File: proposals/tree_proposals.py | ||
| 📝 File: proposals/multi_member_tree_proposals.py | ||
|
|
||
| * Both epsilon_tree_bipartition() and epsilon_tree_bipartition_multi_member() have changes - epsilon_tree_bipartition() is in a different module - it used to be in tree but is now in proposals. epsilon_tree_bipartition_multi_member() is new. However, in both cases, the routines are only ever used inside the file that they are defined in, so while they are technically externally visible, I am not sure anyone cares... | ||
|
|
||
| 📝 File: updaters/compactness.py | ||
|
|
||
| 🔸 [Global] REMOVED function: flips | ||
|
|
||
| Note: this routine seems to have never been used and all it did | ||
| was return partition.flips, so I don't think mentioning it | ||
| is worth the noise. | ||
|
|
||
| 📝 File: partition/partition.py | ||
|
|
||
| ⚠️ [Class Partition] SIGNATURE CHANGED: flip | ||
| Old: (self, flips) | ||
| New: (self, flips, flips_passed_in_use_original_nx_node_ids) | ||
|
|
||
| 📄 [ADDED FILE] tree/__init__.py | ||
|
|
||
| Note: One can still import the module, "tree", but its implementation has been split into several files. | ||
|
|
||
| 📝 File: accept.py | ||
|
|
||
| 🔹 [ADDED CLASS] AcceptanceFn | ||
|
|
||
| 📝 File: graph.py | ||
|
|
||
| 🔹 [ADDED CLASS] GraphValidationError | ||
|
|
||
| 🔹 [Class Graph] ADDED function: laplacian_matrix(self) | ||
| 🔹 [Class Graph] ADDED function: normalized_laplacian_matrix(self) | ||
|
|
||
| Note: Previous code relied on NetworkX Laplacian functions | ||
|
|
||
| 🔹 [Class Graph] ADDED function: generic_bfs_predecessors(self, root_node_id) | ||
| 🔹 [Class Graph] ADDED function: predecessors(self, root_node_id) | ||
| 🔹 [Class Graph] ADDED function: generic_bfs_successors(self, root_node_id) | ||
| 🔹 [Class Graph] ADDED function: successors(self, root_node_id) | ||
| 🔹 [Class Graph] ADDED function: generic_bfs_successors_generator(self, root_node_id) | ||
|
|
||
| Note: Required because NetworkX and RustworkX have different ways of dealing with predecessors and successors. These routines insulate user code from having to know what the embedded graph object is. | ||
|
|
||
| 🔹 [Class Graph] ADDED function: verify_graph_is_valid(self, thorough) | ||
|
|
||
| 🔹 [Class Graph] ADDED function: is_directed(self) | ||
|
|
||
| 🔹 [Class Graph] ADDED function: convert_from_nx_to_rx(self) | ||
|
|
||
| Note: Used to convert from NetworkX.Graph to RustworkX.PyGraph when creating a Partition object. | ||
|
|
||
| 🔹 [Class Graph] ADDED function: minimum_spanning_tree_from_edge_weight(self, edge_weight_attribute_name) | ||
|
|
||
| 🔹 [Class Graph] ADDED function: num_connected_components(self) | ||
| 🔹 [Class Graph] ADDED function: is_node_set_connected(self, nodes) | ||
| 🔹 [Class Graph] ADDED function: is_connected(self) | ||
| 🔹 [Class Graph] ADDED function: subgraphs_for_connected_components(self) | ||
|
|
||
| 📝 File: partition/partition.py | ||
|
|
||
| 🔹 [Class Partition] ADDED function: assignment_vector(self) | ||
|
|
||
| 📝 File: optimization/gingleator.py | ||
|
|
||
| 🔹 [ADDED CLASS] GingleScoreFn | ||
|
|
||
| 📝 File: partition/assignment.py | ||
|
|
||
| 🔹 [Class Assignment] ADDED function: to_vector(self) | ||
|
|
||
| 🔹 [Class Assignment] ADDED function: new_assignment_convert_old_node_ids_to_new_node_ids(self, node_id_mapping) | ||
|
|
||
| Note: Supports translating node_ids in an Assignment object - typically translating from the internal RustworkX node_ids used when running a chain back to the "original" NetworkX node_ids so that post processing a chain's data can use the "original" NetworkX node_ids. | ||
|
|
||
| 📝 File: proposals/spectral_proposals.py | ||
|
|
||
| 🔹 [Global] ADDED function: build_spectral_recom_proposal_fn(weight_type, lap_type) | ||
|
|
||
| 📝 File: updaters/flows.py | ||
|
|
||
| 🔹 [Global] ADDED function: create_edge_flow() | ||
|
|
||
| 🔹 [ADDED CLASS] EdgeFlowUpdateFn | ||
|
|
||
| ### Changes in function signature to add RNG param: | ||
|
|
||
|
|
||
| 📝 File: accept.py | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: always_accept | ||
| Old: (partition) | ||
| New: (partition, rng) | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: cut_edge_accept | ||
| Old: (partition) | ||
| New: (partition, rng) | ||
|
|
||
| 📝 File: chain.py | ||
| ⚠️ [Class MarkovChain] SIGNATURE CHANGED: __init__ | ||
| Old: (self, proposal, constraints, accept, initial_state, total_steps) | ||
| New: (self, proposal_fn, constraints, acceptance_fn, initial_partition, total_steps, rng) | ||
|
|
||
| 📝 File: proposals/tree_proposals.py | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: reversible_recom | ||
| Old: (partition, pop_col, pop_target, epsilon, balance_edge_fn, M, repeat_until_valid, choice) | ||
| New: (partition, pop_col, pop_target, epsilon, max_balanced_edge_cuts, find_balanced_edge_cuts_fn, repeat_until_valid, rng) | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: recom | ||
| Old: (partition, pop_col, pop_target, epsilon, node_repeats, region_surcharge, method) | ||
| New: (partition, pop_col, pop_target, epsilon, node_repeats, region_surcharge, bipartition_tree_fn, pair_selection, rng) | ||
|
|
||
| 📝 File: optimization/gingleator.py | ||
|
|
||
| ⚠️ [Class Gingleator] SIGNATURE CHANGED: __init__ | ||
| Old: (self, proposal, constraints, initial_state, minority_perc_col, threshold, score_function, minority_pop_col, total_pop_col, min_perc_column_name) | ||
| New: (self, proposal_fn, constraints, initial_state, minority_perc_col, threshold, score_fn, minority_pop_col, total_pop_col, min_perc_column_name, rng) | ||
|
|
||
| 📝 File: optimization/optimization.py | ||
|
|
||
| ⚠️ [Class SingleMetricOptimizer] SIGNATURE CHANGED: __init__ | ||
| Old: (self, proposal, constraints, initial_state, optimization_metric, maximize, step_indexer) | ||
| New: (self, proposal_fn, constraints, initial_state, optimization_metric_fn, maximize, step_indexer, rng) | ||
|
|
||
| 📝 File: partition/partition.py | ||
|
|
||
| ⚠️ [Class Partition] SIGNATURE CHANGED: from_random_assignment | ||
| Old: (cls, graph, n_parts, epsilon, pop_col, updaters, use_default_updaters, flips, method) | ||
| New: (cls, graph, n_parts, epsilon, pop_col, updaters, use_default_updaters, partition_fn, rng) | ||
|
|
||
| 📝 File: proposals/proposals.py | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: propose_flip_every_district | ||
| Old: (partition) | ||
| New: (partition, rng) | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: propose_random_flip | ||
| Old: (partition) | ||
| New: (partition, rng) | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: slow_reversible_propose | ||
| Old: (partition) | ||
| New: (partition, rng) | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: propose_chunk_flip | ||
| Old: (partition) | ||
| New: (partition, rng) | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: propose_any_node_flip | ||
| Old: (partition) | ||
| New: (partition, rng) | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: slow_reversible_propose_bi | ||
| Old: (partition) | ||
| New: (partition, rng) | ||
|
|
||
| 📝 File: proposals/spectral_proposals.py | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: spectral_cut | ||
| Old: (graph, part_labels, weight_type, lap_type) | ||
| New: (subgraph, part_labels, weight_type, lap_type, rng) | ||
|
|
||
| ⚠️ [Global] SIGNATURE CHANGED: spectral_recom | ||
| Old: (partition, weight_type, lap_type) | ||
| New: (partition, weight_type, lap_type, rng) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a lot of changes to the public signatures, and they might be easiest to organize this in the following way:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started down the path of documenting every place where a parameter name was changed to end in "_fn" and then realized that I was violating the "terse" change-log goal.
This is where I stopped:
I then shifted to just showing one example with the assumption that any code that used the old named parameter would be flagged, and users could easily just say: OK - try adding an "_fn" to the name...
However, if you really want the entire list, I can do that...
Renamed parameters that accept functions
Parameters accepting functions now generally have names that use the _fn suffix:
This is only an issue for function calls using named parameters.
An example of this is the renaming of "proposal" to "proposal_fn" in the constructor for a MarkovChain object:
Old:
New:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the deprecation shims in place, and the minimality of the change (post-fixing
_fn), this is probably sufficient. I'll handle the emails of anyone who is confused