Spaces:
Running
Running
File size: 4,624 Bytes
c216121 7b2a37a c216121 7b2a37a 6bc6ef3 c216121 ab93852 ae32abe ab93852 ae32abe 7b2a37a ab93852 c216121 7b2a37a c216121 7b2a37a c216121 7b2a37a c216121 7b2a37a c216121 7b2a37a c216121 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | ---
title: SolverForge Field Service Routing
emoji: 🧰
colorFrom: indigo
colorTo: blue
sdk: docker
app_port: 7860
pinned: false
license: apache-2.0
short_description: SolverForge field-service routing example
---
# SolverForge FSR
`solverforge-fsr` is a SolverForge field-service routing example with retained
jobs, route geometry, technician schedules, and a browser map workspace.
It answers one concrete question:
"Given technicians, service visits, skills, parts, shifts, territories, and
road-network travel, which technician should serve each visit and in what
order?"
## Hugging Face Space Deployment
This repo is Docker-Space ready. Hugging Face reads the README front matter,
builds `Dockerfile`, and expects the app to bind `PORT=7860`.
Local Space-equivalent commands:
```sh
make space-build
make space-run
```
Full local readiness check:
```sh
make ci-local
```
The Space image is self-contained: it builds against published crates.io
packages, copies `static/`, `solver.toml`, and `solverforge.app.toml`, and runs
the release binary `solverforge_fsr`.
## Versioning
The app package version is `1.0.1`; the release binary is `solverforge_fsr`.
- CLI version used to scaffold this project: `2.0.3`
- SolverForge runtime target for this scaffold: `solverforge 0.11.1`
- SolverForge UI target for this scaffold: `solverforge-ui 0.6.5`
- SolverForge maps target for this scaffold: `solverforge-maps 2.1.4`
- Runtime dependency currently wired into `Cargo.toml`: `crates.io: solverforge 0.11.1`
- Frontend UI dependency currently wired into `Cargo.toml`: `crates.io: solverforge-ui 0.6.5`
- Maps dependency currently wired into `Cargo.toml`: `crates.io: solverforge-maps 2.1.4`
This project was scaffolded by `solverforge-cli`, and it currently targets `SolverForge crate target 0.11.1` through the configured crate dependency targets.
`solverforge-core` is a direct dependency because the 0.11 custom
incremental-constraint API exposes `ConstraintRef`, while the top-level facade
does not re-export that type.
## What SolverForge Is Doing Here
- `ServiceVisit` is a problem fact: a customer job the solver must place in a
technician route.
- `TechnicianRoute` is the planning entity: each technician owns one mutable
route.
- `TechnicianRoute.visits` is the list planning variable.
- `FieldServicePlan` is the planning solution.
- Constraints score assignment coverage, route reachability, shift capacity,
required skills, required parts, time windows, priority slack, territory
affinity, travel time, and workload balance.
- `solver.toml` selects the construction and local-search policy.
The app ships one standard Bergamo field-service dataset and prepares full
routing data when a job is created so snapshots can expose per-segment geometry.
## Quick Start
```sh
make run-release
```
Then open `http://localhost:7860`.
To inspect the command surface:
```sh
make help
```
## Development
```sh
# Add a new constraint
solverforge generate constraint my_rule --unary --hard
# Add a domain entity
solverforge generate entity worker --planning-variable shift_idx
# Add a problem fact
solverforge generate fact location
# Remove a resource
solverforge destroy constraint my_rule
```
## Project Structure
| Directory | Purpose |
|-----------|--------|
| `src/domain/` | Planning entities, facts, and solution struct |
| `src/constraints/` | Constraint definitions (scored by the solver) |
| `src/solver/` | Solver service and configuration |
| `src/api/` | HTTP routes and DTOs |
| `src/data/` | Data loading and generation |
| `static/` | Browser UI, SolverForge UI config, and generated UI model |
| `Dockerfile` | Multi-stage Rust 1.95 Alpine build for the Hugging Face Docker Space |
| `Makefile` | Local development, validation, and Space image commands |
| `solverforge.app.toml` | Scaffolded app/domain contract |
| `solver.toml` | Solver configuration (termination, phases) |
## REST API
- `GET /health`
- `GET /info`
- `GET /demo-data`
- `GET /demo-data/{id}`
- `POST /jobs`
- `GET /jobs/{id}`
- `GET /jobs/{id}/status`
- `GET /jobs/{id}/snapshot`
- `GET /jobs/{id}/analysis`
- `GET /jobs/{id}/routes`
- `POST /jobs/{id}/pause`
- `POST /jobs/{id}/resume`
- `POST /jobs/{id}/cancel`
- `DELETE /jobs/{id}`
- `GET /jobs/{id}/events`
Route geometry is returned by `/jobs/{id}/routes` with segment-level geometry
status. Unreachable road-network legs are reported as non-routed segments, so
one infeasible leg does not hide the rest of the snapshot geometry.
## Validation
Standard validation:
```sh
make test
```
Full local Space validation:
```sh
make ci-local
```
|