A template for creating constraint optimization applications with SolverForge.
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# Start the application
run-appVisit http://localhost:8080/q/swagger-ui for the API documentation.
- Create a new Space at https://huggingface.co/new-space
- Select Docker as the SDK
- Upload all files from this repository
- The Space will automatically build and deploy
Your app will be live at https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE_NAME
my-quickstart/
├── pyproject.toml # Package configuration
├── Dockerfile # Container definition (HuggingFace compatible)
├── README.md # This file
├── logging.conf # Logging configuration
├── src/my_quickstart/
│ ├── __init__.py # App entry point
│ ├── domain.py # Domain model (@dataclass + @planning_entity)
│ ├── constraints.py # Constraint definitions (@constraint_provider)
│ ├── solver.py # Solver configuration
│ ├── rest_api.py # FastAPI endpoints
│ ├── demo_data.py # Sample datasets
│ └── json_serialization.py # Pydantic utilities
├── tests/
│ └── test_constraints.py # Constraint verification tests
└── static/
└── index.html # Optional web UI
from dataclasses import dataclass
from typing import Annotated
from solverforge_legacy.solver.domain import (
planning_entity, planning_solution,
PlanningId, PlanningVariable,
PlanningEntityCollectionProperty,
ProblemFactCollectionProperty,
ValueRangeProvider, PlanningScore,
)
# Problem facts (immutable input data)
@dataclass
class Resource:
name: Annotated[str, PlanningId]
capacity: int
# Planning entities (what the solver assigns)
@planning_entity
@dataclass
class Task:
id: Annotated[str, PlanningId]
duration: int
resource: Annotated[Resource | None, PlanningVariable] = None
# Solution container
@planning_solution
@dataclass
class Schedule:
resources: Annotated[list[Resource], ProblemFactCollectionProperty, ValueRangeProvider]
tasks: Annotated[list[Task], PlanningEntityCollectionProperty]
score: Annotated[HardSoftScore | None, PlanningScore] = Nonefrom solverforge_legacy.solver.score import (
constraint_provider, ConstraintFactory,
HardSoftScore, Joiners, ConstraintCollectors,
)
@constraint_provider
def define_constraints(constraint_factory: ConstraintFactory):
return [
resource_capacity(constraint_factory),
minimize_makespan(constraint_factory),
]
def resource_capacity(constraint_factory: ConstraintFactory):
return (
constraint_factory.for_each(Task)
.group_by(lambda t: t.resource, ConstraintCollectors.sum(lambda t: t.duration))
.filter(lambda resource, total: total > resource.capacity)
.penalize(HardSoftScore.ONE_HARD, lambda r, total: total - r.capacity)
.as_constraint("Resource capacity")
)pytest tests/ -v| Endpoint | Method | Description |
|---|---|---|
/demo-data |
GET | List available demo datasets |
/demo-data/{id} |
GET | Get specific demo data |
/schedules |
POST | Start solving (returns job_id) |
/schedules/{id} |
GET | Get current solution |
/schedules/{id} |
DELETE | Stop solving |
/schedules/analyze |
PUT | Analyze solution score |
/q/swagger-ui |
GET | API documentation |
- Python 3.10+
- JDK 17+ (for solverforge-legacy)
MIT