Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions gerrychain/graph/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
"""
This module provides the Graph class that is used
This module implements the Graph class that is used
by GerryChain code.

It exposes standard graph functionality for a dual-graph
containing nodes and edges. Both nodes and edges can have
data associated with them.

A Graph object is typically created by first creating
a NetworkX Graph object and then converting it to
a NetworkX.Graph object and then converting it to
a GerryChain Graph object using from_networkx().

Internally, a Graph object contains and embedded graph
For instance:

import networkx
from gerrychain import Graph

# Create a NetworkX graph
nx_graph = networkx.Graph()
nx_graph.add_edges_from(...)

# Create a GerryChain graph from the NetworkX graph
my_gerrychain_graph = Graph.from_networkx(nx_graph)

Internally, a Graph object contains an embedded graph
object based either on NetworkX or RustworkX. After
creating a Partition object in GerryChain, the embedded
graph object is converted to be based on RustworkX (for
performance reasons).

The class Graph is the only part of this module that
is intended to be used directly by users of GerryChain.
"""

from .adjacency import *
Expand Down
175 changes: 175 additions & 0 deletions v1.0.0_changelog.md

Copy link
Copy Markdown
Collaborator

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:

Renamed parameters

Parameters accepting functions now generally use the _fn suffix:

  • proposalproposal_fn
    • MarkovChain
    • SingleMetricOptimizer
    • Gingleator

Copy link
Copy Markdown
Collaborator Author

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:

* proposal → proposal_fn
    * MarkovChain
    * SingleMetricOptimizer
    * Gingleator
* ??? → acceptance_fn
    * MarkovChain
    * SingleMetricOptimizer.short_burts()
    * ???
* ??? → value_fn
    * Bounds
* ??? → score_fn
    * Gingleator
    * SingleMetricOptimizer
* ??? → optimization_metric_fn
    * SingleMetricOptimizer
* ??? → beta_fn
    * SingleMetricOptimizer.simulated_annealing()
* ??? → container_fn
    * assignmewnt.level_sets()---

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:

    my_chain = MarkovChain(
        proposal = my_proposal,
        ...
    )
    

    New:

    my_chain = MarkovChain(
        proposal_fn = my_proposal,
        ...
    )
    

Copy link
Copy Markdown
Collaborator

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The 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

  1. Creating a file called "docs/topics/CONTRIBUTING.md" and ad: this to it:

```{include} ../../CHANGELOG.md
```

  1. In docs/index.md, we should update the format to look like

```{toctree}
:hidden:
:caption: Topics
:maxdepth: 1

topics/v1p0p0_migration_guide
topics/reproducibility
topics/tools
```

```{toctree}
:hidden:
:caption: Help and Project
:maxdepth: 1

topics/changelog
topics/contributing
topics/reporting
```

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The 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...

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The 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,175 @@
## [v1.0.0] - August 2026

### Added
Comment thread
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 method to create a fictional 8x8 grid graph of 64 unit-population nodes that is used in the User Guide.

* gerrymandria()


* 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 grid:

* create_grid_graph() renamed to be: create_grid_nx_graph()

#### 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:
```
my_chain = MarkovChain(
proposal = my_proposal,
...
)
```
New:
```
my_chain = MarkovChain(
proposal_fn = my_proposal,
...
)
```
### Removed

#### Removed the pre-1.0 NetworkX-derived Graph interface.

* gerrychain.Graph is no longer a subclass of networkx.Graph.

See the migration guide for the replacement graph operations.

frm: TODO: Add link for migration guide above.

#### Removed the old instantiable and callable ReCom interface.

* The old ReCom class was instantiable and callable. It has been replaced with an interface that implements a namespace that defines functions that generate proposal functions.

See the ??? #### The `ReCom` Namespace for details.

frm: TODO: Add link for ??? the discussion in the Migration Guide for details.

### Deprecated

#### Pre-1.0 proposal and acceptance callbacks that lack `rng= `.

* The callbacks now support a "reproducibility" parameter, `rng= `, that defines a random number generator. This allows the user to control the initial conditions so that the behavior of GerryChain is deterministic.

For more details see the reproducibility guide. [link-name](https://ibm.com)

frm: TODO: add link to reproducibility guide

#### Legacy constructor and method parameter names for MarkovChain, Gingleator, SingleMetricOptimizer, etc.

* The legacy versions of these remain temporarily supported with warnings.
Loading