Skip to main content

Solvers for placing points along chains

Project description

chainsolvers

chainsolvers is a Python library for solving point placement along chains problems — for example, distributing activities along activity chains to feasible locations. It provides pluggable solver routines, together with configurable scorers and selectors, to flexibly evaluate and select candidate solutions.

Quickstart

Use the two-step runner: setup(...) -> RunnerContext and solve(ctx=..., plans_df=...).

import chainsolvers as cs
import pandas as pd
import numpy as np
import logging

logging.basicConfig(level=logging.INFO)

# 1) Candidate locations
# Provide exactly one of: locations_df, locations_dict, or locations_tuple (these are just different ways of representing the same thing)
# df is probably the easiest coming from a csv, geopackage or similar, tuple is the internal format
locations_df = pd.DataFrame([
    # minimal columns: id, act_type, x, y
    # optional: name, potentials (plural, one per possible activity type at this location, set to 0 if not specified)
    {"activities": "work; business; leisure", "id": "1", "x": 15.0, "y": 13.0, "name": "Business Factory"},
    {"activities": "leisure", "id": "2", "x": 10.0, "y": 10.0, "potentials": 100000.0, "name": "Central Park"},
    {"activities": "education; sports", "id": "3", "x": 10.0, "y": 10.0, "potentials": "5000.0; 60", "name": "Big School"},
])

locations_dict = {
    "work": {
        "1": {"coordinates": [15.0, 13.0], "name": "Business Factory"},
    },
    "business": {
        "1": {"coordinates": [15.0, 13.0], "name": "Business Factory"},
    },
    "leisure": {
        "1": {"coordinates": [15.0, 13.0], "name": "Business Factory"},
        "2": {"coordinates": [10.0, 10.0], "potential": 100000.0, "name": "Central Park"}, # potential, singular
    },
    "education": {
        "3": {"coordinates": [10.0, 10.0], "potential": 5000.0, "name": "Big School"},
    },
    "sports": {
        "3": {"coordinates": [10.0, 10.0], "potential": 60.0, "name": "Big School"},
    },
}

locations_tuple = (
    {
        "work":      np.array(["1"], dtype=object),
        "business":  np.array(["1"], dtype=object),
        "leisure":   np.array(["1", "2"], dtype=object),
        "education": np.array(["3"], dtype=object),
        "sports":    np.array(["3"], dtype=object),
    },
    {
        "work":      np.array([[15.0, 13.0]], dtype=float),
        "business":  np.array([[15.0, 13.0]], dtype=float),
        "leisure":   np.array([[15.0, 13.0], [10.0, 10.0]], dtype=float),
        "education": np.array([[10.0, 10.0]], dtype=float),
        "sports":    np.array([[10.0, 10.0]], dtype=float),
    },
    {
        "work":      np.array([0], dtype=float),
        "business":  np.array([0], dtype=float),
        "leisure":   np.array([0, 100000.0], dtype=float),
        "education": np.array([5000.0], dtype=float),
        "sports":    np.array([60.0], dtype=float),
    },
)

# 2) Create a runner context
ctx = cs.setup(
    locations_df=locations_df,  # or locations_dict= or locations_tuple=...
    # --- optional parameters ---
    # solver="carla",           # defaults to "carla"
    # parameters={              # parameters for the solver (uses default values if not specified)
    #     "number_of_branches": 50,
    #     "candidates_complex_case": 100,
    #     "candidates_two_leg_case": 40,
    #     "anchor_strategy": "lower_middle",  # {'lower_middle','upper_middle','start','end'}
    #     "selection_strategy_complex_case": "top_n_spatial_downsample",
    #     "selection_strategy_two_leg_case": "top_n",
    #     "max_iterations_complex_case": 100,
    # },
    # rng_seed=42,              # or pass a numpy Generator
    # scorer=CustomScorer(),    # uses default scorer if not specified
    # selector=CustomSelector() # uses default selector if not specified
    # progress=tqdm,            # for progress bars, use your own if you want, no progress bars shown if not specified
    # visualizer=CustomVisualizer(), 
)

# 3) Input plans. Minimum required columns:
#    unique_person_id, unique_leg_id, to_act_type, distance_meters, from_x, from_y, to_x, to_y
plans_df = pd.DataFrame([
    {"unique_person_id": "p1", "unique_leg_id": "p1-1", "to_act_type": "work", "distance_meters": 5000,
     "from_x": 10.0, "from_y": 10.0, "to_x": float("nan"), "to_y": float("nan")},
    {"unique_person_id": "p1", "unique_leg_id": "p1-2", "to_act_type": "home", "distance_meters": 4900,
     "from_x": float("nan"), "from_y": float("nan"), "to_x": 300.0, "to_y": 350.4},
])

# 4) Solve
result_df, result_plans, valid = cs.solve(ctx=ctx, plans_df=plans_df)

print(valid)
print(result_df)
print(result_plans)

Returns

A tuple of three elements (in order):

  • result_df: pandas.DataFrame (always returned). Placed plans in same df format as input plans.
  • result_plans: SegmentedPlans (frozendict[str, tuple[Segment, ...]]) or None. Results in the internal SegmentedPlans (may be useful, else just ignore).
  • valid: bool. Whether the output validation succeeded.

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

chainsolvers-0.1.0.tar.gz (32.4 kB view details)

Uploaded Source

Built Distribution

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

chainsolvers-0.1.0-py3-none-any.whl (34.6 kB view details)

Uploaded Python 3

File details

Details for the file chainsolvers-0.1.0.tar.gz.

File metadata

  • Download URL: chainsolvers-0.1.0.tar.gz
  • Upload date:
  • Size: 32.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for chainsolvers-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c69621ff4efb3b7fac31a3edab97fb685548644403394e10b8d14cc807520ea7
MD5 dc2df1706379d8d75d2501d2fd1723bb
BLAKE2b-256 07bb02114566837b76fe4a4fa277fa1598148b7a7d365aab0762b5c60f0516b1

See more details on using hashes here.

File details

Details for the file chainsolvers-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: chainsolvers-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 34.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for chainsolvers-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e9e9b3283d4c9d0385db6126db1f66dbfc785467b0261f4786da12fced4bd7e2
MD5 48fdd942c1ac11322d41b50b63467c89
BLAKE2b-256 4a7947de9b29e83fc63920f800bab1b4002aa8b4ca11e6e9701e5e3d566f2ceb

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