Skip to main content

Solving combinatorial reconfiguration problems.

Project description

Reconfillion - Python interface for combinatorial reconfiguration problems

Reconfillion was released as version 1.0.0 on April 22, 2024. The older version of reconfillion before that date exists on https://github.com/junkawahara/reconfillion-kari , but is not compatible with this version.

Reconfillion is a tool for solving combinatorial reconfiguration problems. It works with graphillion, which means that combinatorial reconfiguration problems of graph classes that are supported by graphillion can be solved by reconfillion.

Requirements

License

MIT License

Quick install

You can install reconfillion via pip.

pip install reconfillion

Tutorial

A combinatorial reconfiguration problem asks, given a start state s and a goal state t (each a subset of elements such as edges or vertices) drawn from a search space of valid states, for a step-by-step reconfiguration sequence that transforms s into t so that every intermediate state is valid and consecutive states differ by a single legal move. What counts as a move is decided by the chosen model; reconfillion supports token jumping (tj), token addition/removal (tar), and token sliding (ts).

Let's consider to solve the spanning tree reconfiguration problem. In reconfillion (and graphillion), an edge is represented by a tuple of two vertices, and a graph is represented by a list of edges.

# complete graph with 4 vertices [1, 2, 3, 4]
graph = [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]

We import graphillion and reconfillion, and make GraphSet of all the spanning trees on the graph.

from graphillion import GraphSet
from reconfillion import reconf

GraphSet.set_universe(graph) # See the graphillion manual.
spanning_trees = GraphSet.trees(is_spanning = True)

Token jumping (tj)

Under the token jumping model a single move removes one token and adds one token at the same time, so the size of the state stays fixed (|s| must equal |t|). Thinking of each element in a state as a token, one move picks up a token and drops it anywhere else, as long as the resulting state is still valid.

By doing the following method, we can obtain the reconfiguration sequence between s and t.

s = [(1, 2), (1, 3), (1, 4)] # start spanning tree
t = [(1, 4), (2, 4), (3, 4)] # goal spanning tree

# obtain a reconfiguration sequence between s and t under the token jumping model.
reconf_sequence = reconf.get_reconf_seq(s, t, spanning_trees, model = 'tj')

# obtained [[(1, 4), (2, 4), (3, 4)], [(1, 2), (1, 4), (2, 4)], [(1, 2), (1, 3), (1, 4)]]

The returned list is a shortest sequence: consecutive spanning trees differ by exactly one swapped edge, and the first/last entries are t/s. If t is unreachable from s, get_reconf_seq returns [].

Token addition/removal (tar)

Under the token addition/removal model a single move adds one token or removes one token, so the size of the state changes by one each step (and s and t may even have different sizes). To keep states meaningful you bound the state size with the keyword arguments lower and upper: every intermediate state must have size within [lower, upper]. Use a lower bound for problems whose feasible states are downward closed (e.g. independent sets, where you must keep at least k tokens) and an upper bound for upward-closed problems (e.g. dominating sets). Either bound may be None, meaning "no bound in that direction".

from graphillion import VertexSetSet

VertexSetSet.set_universe()
independent_sets = VertexSetSet.independent_sets(graph)

s = [1, 3] # start independent set
t = [2, 4] # goal independent set

# reconfigure under token addition/removal, keeping the size in [1, 2].
reconf_sequence = reconf.get_reconf_seq(
    s, t, independent_sets, model = 'tar', lower = 1, upper = 2)

If s or t has a size outside [lower, upper], get_reconf_seq raises ValueError.

Token sliding (ts)

Under the token sliding model a single move slides one token along an edge to an adjacent vertex, keeping the state size fixed (so |s| must equal |t|). Adjacency cannot be derived from the search space alone, so the ts model requires a graph argument: a list of (a, b) pairs of adjacent elements. For independent set reconfiguration this is simply the underlying graph's edges.

from graphillion import GraphSet, VertexSetSet

path = [(1, 2), (2, 3), (3, 4), (4, 5)] # path graph 1-2-3-4-5
GraphSet.set_universe(path)
VertexSetSet.set_universe(list(range(1, 6)))
independent_sets = VertexSetSet.independent_sets(path)

s = [1] # start: a single token on vertex 1
t = [5] # goal:  the token on vertex 5

# slide the token along the path; `graph` defines which moves are legal.
reconf_sequence = reconf.get_reconf_seq(
    s, t, independent_sets, model = 'ts', graph = path)

# obtained [{1}, {2}, {3}, {4}, {5}]

The token can only step to a neighbour, so unlike token jumping it walks 1 -> 2 -> 3 -> 4 -> 5 instead of jumping straight to 5. Omitting graph for ts (or passing it for any other model) raises ValueError.

Farthest state from a single start (get_longest_shortest_seq)

Sometimes you have only a start state s and want the hardest target to reach from it: a state whose shortest reconfiguration distance from s is as large as possible (the eccentricity of s in the move graph). get_longest_shortest_seq takes only s (no t), explores every state reachable from s, picks a farthest one, and returns a shortest sequence to it.

# reuse the spanning trees from the tutorial above
s = [(1, 2), (1, 3), (1, 4)] # start spanning tree

# a shortest sequence from s to one of the farthest spanning trees (tj model).
reconf_sequence = reconf.get_longest_shortest_seq(s, spanning_trees, model = 'tj')

# reconf_sequence[0] == s, and its length - 1 is the farthest distance from s.

It supports the same tj, tar, and ts models (tar takes the same lower / upper bounds; ts takes the same required graph). If s cannot make a single legal move, [s] is returned.

Tests

A pytest suite under tests/ exercises the token jumping (tj), token addition/removal (tar), and token sliding (ts) models on a small set of independent set reconfiguration instances bundled in tests/data/ (a subset of the Core Challenge 2022 benchmark; see tests/data/README.md). Install the test dependencies and run pytest:

pip install -e ".[test]"
pytest -s tests/

The -s flag shows a per-instance summary (reachability and sequence length).

Note

This software (and graphillion) needs a lot of memory to solve problems with large-size instances.

Authors

Reconfillion has been developed by Jun Kawahara and Hiroki Yamazaki.

Acknowledgment

This project is/was partially supported by JSPS KAKENHI Grant Numbers JP18H04091, JP20H05794, and JP23H04383.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

reconfillion-1.1.0.tar.gz (17.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

reconfillion-1.1.0-py3-none-any.whl (10.4 kB view details)

Uploaded Python 3

File details

Details for the file reconfillion-1.1.0.tar.gz.

File metadata

  • Download URL: reconfillion-1.1.0.tar.gz
  • Upload date:
  • Size: 17.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for reconfillion-1.1.0.tar.gz
Algorithm Hash digest
SHA256 9818fe8fbf22d12133fa66e8dddee4638dac71ac0a5f55fb8b91bebacf9d1528
MD5 b8465a5d25148ff1b2ad640955082886
BLAKE2b-256 eaed9d20f07e32cb80f6bb4494f297ea29c5b897d3eb521ef200752e5b970e23

See more details on using hashes here.

File details

Details for the file reconfillion-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: reconfillion-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for reconfillion-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6ebc2e43c92739ee1dbc61a0ee9290675bb71041df424c56e12808fa5f03fb76
MD5 7476414760fd7f83cb1313b4e2f09c5a
BLAKE2b-256 7b57b94eced3ba9024a6385901e85bed7b690a60269da7e1be6e94c65f59b83e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page