Python bindings for SolverForge constraint solver
Project description
SolverForge Python
Python bindings for the SolverForge constraint solver.
Installation
pip install solverforge
Quick Start
from solverforge import (
planning_entity, planning_solution, constraint_provider,
PlanningId, PlanningVariable, PlanningListVariable,
HardSoftScore, SolverFactory, TerminationConfig,
)
@planning_entity
class Lesson:
id: str
subject: str
timeslot: str | None = None
room: str | None = None
@planning_solution
class Timetable:
timeslots: list[str]
rooms: list[str]
lessons: list[Lesson]
score: HardSoftScore | None = None
@constraint_provider
def define_constraints(factory):
return [
factory.for_each(Lesson)
.join(Lesson, equal(lambda l: l.room), equal(lambda l: l.timeslot))
.filter(lambda l1, l2: l1.id < l2.id)
.penalize(HardSoftScore.ONE_HARD)
.as_constraint("Room conflict"),
]
# Solve
solver = SolverFactory.create(Timetable, define_constraints)
.with_termination(TerminationConfig.with_spent_limit("PT30S"))
.build()
solution = solver.solve(problem)
Features
Domain Modeling
from solverforge import (
planning_entity, planning_solution,
PlanningVariable, PlanningListVariable,
InverseRelationShadow, IndexShadow, PreviousElementShadow, NextElementShadow,
)
# Standard planning variable
@planning_entity
class Shift:
id: str
employee: str | None = None # Assigned by solver
# List planning variable (vehicle routing)
@planning_entity
class Vehicle:
id: str
visits: list[str] = [] # List of visit IDs, assigned by solver
# Shadow variables (auto-updated when list changes)
@planning_entity
class Visit:
id: str
vehicle: str | None = None # @InverseRelationShadowVariable
index: int | None = None # @IndexShadowVariable
previous: str | None = None # @PreviousElementShadowVariable
next: str | None = None # @NextElementShadowVariable
Constraint Streams
from solverforge import (
equal, less_than, greater_than, overlapping, filtering,
count, sum_, min_, max_, to_list, to_set,
)
@constraint_provider
def constraints(factory):
return [
# forEach / forEachIncludingUnassigned / forEachUniquePair
factory.for_each(Lesson),
factory.for_each_including_unassigned(Lesson),
factory.for_each_unique_pair(Lesson, equal(lambda l: l.timeslot)),
# filter
factory.for_each(Lesson)
.filter(lambda l: l.room is not None),
# join with joiners
factory.for_each(Lesson)
.join(Room, equal(lambda l: l.room, lambda r: r.id)),
# ifExists / ifNotExists
factory.for_each(Lesson)
.if_exists(Conflict, equal(lambda l: l.id, lambda c: c.lesson_id)),
# groupBy with collectors
factory.for_each(Lesson)
.group_by(lambda l: l.room, count())
.filter(lambda room, cnt: cnt > 1)
.penalize(HardSoftScore.ONE_HARD, lambda room, cnt: cnt - 1),
# map / expand / flattenLast
factory.for_each(Vehicle)
.flatten_last(lambda v: v.visits),
]
SolverManager (Multi-Problem Solving)
from solverforge import SolverManager, HttpSolverService
service = HttpSolverService("http://localhost:8080")
manager = SolverManager(Timetable, define_constraints, service)
# Solve multiple problems concurrently
manager.solve("problem-1", problem1)
manager.solve("problem-2", problem2)
# Check solutions
solution = manager.get_best_solution("problem-1")
if solution:
print(f"Score: {solution.score}")
# Terminate
manager.terminate("problem-1")
manager.terminate_all()
ConstraintVerifier (Testing)
from solverforge import ConstraintVerifier
verifier = ConstraintVerifier.build(Timetable, define_constraints)
# Test specific constraint
verifier.verify_that(lambda f: f.for_each(Lesson)...)
.given(lesson1, lesson2)
.penalizes_by(1)
# Test entire solution
verifier.verify_that()
.given_solution(solution)
.scores(HardSoftScore.of(-2, -10))
Score Types
from solverforge import (
SimpleScore, HardSoftScore, HardMediumSoftScore,
BendableScore, SimpleDecimalScore, HardSoftDecimalScore,
)
score = HardSoftScore.of(-2, -15)
print(f"Hard: {score.hard_score}, Soft: {score.soft_score}")
print(f"Feasible: {score.is_feasible()}")
# Arithmetic
combined = score + HardSoftScore.of(0, -5)
Solver Configuration
from solverforge import (
SolverFactory, SolverConfig, TerminationConfig,
EnvironmentMode, MoveThreadCount,
)
solver = SolverFactory.create(Timetable, define_constraints)
.with_termination(
TerminationConfig()
.with_spent_limit("PT5M")
.with_unimproved_spent_limit("PT1M")
.with_best_score_feasible(True)
)
.with_environment_mode(EnvironmentMode.REPRODUCIBLE)
.with_random_seed(42)
.with_move_thread_count(MoveThreadCount.AUTO)
.build()
Requirements
- Python 3.13+ (required for modern AST support)
- Java 21+ (for solver service, auto-started)
License
Apache-2.0
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
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file solverforge-0.3.0.tar.gz.
File metadata
- Download URL: solverforge-0.3.0.tar.gz
- Upload date:
- Size: 238.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
466deb27576a35a8c8bf58a38fb4a93a922f8dc251c2f4cdcdc97b7536c9ea8c
|
|
| MD5 |
d9fabc01373da1df77bcb6e042c28858
|
|
| BLAKE2b-256 |
990332ccf8ca97f7c2f2885c3943e457405e6a05f77d4c6639680d7d74ce04a5
|
Provenance
The following attestation bundles were made for solverforge-0.3.0.tar.gz:
Publisher:
python-publish.yml on SolverForge/solverforge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
solverforge-0.3.0.tar.gz -
Subject digest:
466deb27576a35a8c8bf58a38fb4a93a922f8dc251c2f4cdcdc97b7536c9ea8c - Sigstore transparency entry: 787920186
- Sigstore integration time:
-
Permalink:
SolverForge/solverforge@a5ee68b3f46c6bb143c6b8e316d2415d3f9b876b -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/SolverForge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@a5ee68b3f46c6bb143c6b8e316d2415d3f9b876b -
Trigger Event:
push
-
Statement type:
File details
Details for the file solverforge-0.3.0-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: solverforge-0.3.0-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50e33400c8a2d52f23f3c16ac58e2328fc87c52a663f4eddf9937406a4f526a9
|
|
| MD5 |
7051c3ce6bc1e8cbd7c4d041d1339203
|
|
| BLAKE2b-256 |
cca8cb9f1ab9f220b94f5e13ebead92fe300629d69b3c6932cbebb598de3b858
|
Provenance
The following attestation bundles were made for solverforge-0.3.0-cp310-abi3-win_amd64.whl:
Publisher:
python-publish.yml on SolverForge/solverforge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
solverforge-0.3.0-cp310-abi3-win_amd64.whl -
Subject digest:
50e33400c8a2d52f23f3c16ac58e2328fc87c52a663f4eddf9937406a4f526a9 - Sigstore transparency entry: 787920191
- Sigstore integration time:
-
Permalink:
SolverForge/solverforge@a5ee68b3f46c6bb143c6b8e316d2415d3f9b876b -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/SolverForge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@a5ee68b3f46c6bb143c6b8e316d2415d3f9b876b -
Trigger Event:
push
-
Statement type:
File details
Details for the file solverforge-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: solverforge-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.7 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d333ce93d0f3a8fe8c5539d433acf98b885afac327bca67261afd72a78647e45
|
|
| MD5 |
9dfffe2f27d337699b3cff67ff2695a1
|
|
| BLAKE2b-256 |
da3cd0c27be62fd6082254800cd9bbfff1680b0ee1cf2fb46ff3ee94ae12d37b
|
Provenance
The following attestation bundles were made for solverforge-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
python-publish.yml on SolverForge/solverforge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
solverforge-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
d333ce93d0f3a8fe8c5539d433acf98b885afac327bca67261afd72a78647e45 - Sigstore transparency entry: 787920188
- Sigstore integration time:
-
Permalink:
SolverForge/solverforge@a5ee68b3f46c6bb143c6b8e316d2415d3f9b876b -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/SolverForge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@a5ee68b3f46c6bb143c6b8e316d2415d3f9b876b -
Trigger Event:
push
-
Statement type:
File details
Details for the file solverforge-0.3.0-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: solverforge-0.3.0-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b0e1c8acef89d38c91d0fb0c3858cbefd2e1dfb94036285f794f581c5670581
|
|
| MD5 |
49e118b8edea45a67c9882434a442bef
|
|
| BLAKE2b-256 |
415e14e145765f9109be7ac381038088d9a920917ab0c2956f5a7cf47280c986
|
Provenance
The following attestation bundles were made for solverforge-0.3.0-cp310-abi3-macosx_11_0_arm64.whl:
Publisher:
python-publish.yml on SolverForge/solverforge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
solverforge-0.3.0-cp310-abi3-macosx_11_0_arm64.whl -
Subject digest:
0b0e1c8acef89d38c91d0fb0c3858cbefd2e1dfb94036285f794f581c5670581 - Sigstore transparency entry: 787920196
- Sigstore integration time:
-
Permalink:
SolverForge/solverforge@a5ee68b3f46c6bb143c6b8e316d2415d3f9b876b -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/SolverForge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@a5ee68b3f46c6bb143c6b8e316d2415d3f9b876b -
Trigger Event:
push
-
Statement type: