Every operation has rules that are unique. "VIP customers must be visited first." "A route entering a restricted zone must end there." "No more than two fragile-goods stops per shift." These rules define the difference between a generic plan and a plan your dispatchers trust.
In other solvers, implementing a custom rule requires deep knowledge of the solver's internals, weeks of development, and ongoing maintenance. In JOpt, it takes one Java class, one method override, and five minutes. Your rule participates in every solution evaluation alongside all built-in cost components. No solver modification. No recompilation of the engine.
The architecture is so simple that rules could be expressed in a scripting language and defined by end customers directly. That is the design goal.
Generic solvers cover 90% of routing and scheduling requirements out of the box. The remaining 10% is what makes your operation unique: company-specific policies, regulatory requirements, customer preferences, operational heuristics that dispatchers have refined over years. In traditional optimization engines, implementing these rules is a project in itself.
In Google OR-Tools, custom constraints require defining new dimensions, writing callback functions, and carefully managing solver state. Others: Custom rules require Constraint Streams or Drools rules, score calculation tuning, and solver configuration adjustments. Both approaches demand deep expertise in the solver's architecture and ongoing maintenance when the solver version changes.
JOpt's Open Assessor was designed to make this effortless. Write a method that receives context and returns cost adjustments. That is the entire contract.
“No customer scenario is impossible. If you can express a rule precisely, you can integrate it cleanly. The pattern is what matters: where to inject logic, how to attach it, how cost and violations are updated.”
JOpt.TourOptimizer DocumentationImplement a restriction class. Override the evaluation method. Wire it into the optimization scheme. Run the optimizer. Your rule participates in every solution candidate alongside distance, time, capacity, and all other cost components. Custom cost contributions are tracked separately for diagnostics and explainability.
Node-level restrictions evaluate each visited node in route context. You see the node, the previous element, the planned arrival time, the opening-hours selection. Rules like "high-priority early," "custom deadlines," and "sequence preferences" fit naturally here.
Route-level restrictions evaluate the entire route. You see all assigned nodes, total distance, working time, territory crossings. Rules like "max 2 hazmat stops," "must end in starting territory," and "minimum replenishment visits" fit here.
Both levels produce structured violation reports with type identifiers, contextual values, and human-readable messages. These reports surface in planning UIs, comparison tools, and audit logs. Your custom rule is not a black box. It is an explainable, reportable cost contribution.
In OR-Tools: define new dimensions, write callbacks, manage solver state. In Timefold: write Constraint Streams or Drools rules, tune score calculation, adjust solver config. Both require deep solver knowledge and ongoing maintenance across version upgrades. In JOpt: one class, one method, wire and run. The contract is stable across engine versions.
The restriction contract is deliberately minimal: receive context, return cost adjustments. This architecture is simple enough that restrictions could be expressed in a scripting language (JavaScript, Groovy, Python) and defined by end customers through a rule builder, without writing Java. The path from "developer implements rules" to "end customer defines rules" is a tooling step, not an architecture change.
JOpt's Open Assessor provides a stable, minimal contract for custom business logic. One method, full context, cost injection. No solver internals exposed. No maintenance burden on version upgrades. The same pattern from prototype to production.
| Traditional solver extensibility | JOpt Open Assessor |
|---|---|
| × Weeks to implement a custom rule | ✓ Minutes from idea to running rule |
| × Deep solver internals knowledge | ✓ One method override, full context |
| × Breaks on solver version updates | ✓ Stable contract across versions |
| × Custom costs invisible in reports | ✓ Structured violations, fully reportable |
| × Developer-only rule definition | ✓ Simple enough for scripting/rule builders |
"VIP customers visited first." "No more than 3 hazmat stops per route." "Penalize direction changes." "Exponential deadline penalty beyond 11:00 AM." "Importance-ordered sequences." "Route must contain a depot return if load exceeds threshold." Any rule you can express as a condition on a node or a route.
Every custom rule produces structured violation details: type identifier, severity, contextual values, human-readable message. These appear in comparison tools, planning UIs, and audit reports. Your dispatchers know not just what the optimizer decided, but why.
Run any Open Assessor example. Modify the restriction logic. Watch the optimizer respond to your custom rule in the next run.