OptalCP 2026.1.0 Release
This release introduces a native Python API, bringing OptalCP to a wider audience of optimization practitioners. The TypeScript API has been refined to align with the new Python interface, resulting in cleaner, more intuitive syntax across both languages.
On the solver side, we've added automatic configuration through presets, making it easier to get good performance without manual parameter tuning. Decision problems now stop automatically after finding the first solution, eliminating a common source of confusion. Discrete resource constraints now support variable maximum capacity, enabling new classes of capacity planning problems.
Highlights
New Python API
OptalCP now has a Python API. The API is designed to be nearly identical to the TypeScript API, making it easy to switch between languages or translate examples.
import optalcp as cp
model = cp.Model()
task = model.interval_var(length=10, name="task")
model.minimize(task.end())
result = model.solve(cp.Parameters(timeLimit=60))
if result.solution:
print(f"Task ends at {result.solution.get_end(task)}")
Key features:
- Method-based style:
model.solve() - Property accessors:
interval.start_min,interval.length_max - Comparison operators:
cumul <= 10and5 < x - Auto-registration of constraints and objectives
TypeScript API Changes
The TypeScript API has been updated to align with the new Python API. Both APIs now share nearly identical syntax. The main changes are:
model.constraint()renamed tomodel.enforce()for claritysolve(model, ...)replaced bymodel.solve()- Functions merged into overloads:
model.cumulPlus()is now justmodel.plus(), working for both integer and cumulative expressions - Getter/setter methods replaced with properties
- And many more...
Old functions remain available but are deprecated. See TypeScript API Changes below for the full list.
Automatic Solver Configuration with Presets
The new preset parameter simplifies solver configuration by setting optimal defaults for multiple parameters at once:
- Auto (default): Automatically selects preset based on problem size
- Default: Balanced configuration with maximum propagation and mixed search strategies
- Large: Optimized for problems with more than 100,000 variables
Variable Capacity for Discrete Resources
Discrete resource constraints now support variable maximum capacity. Instead of a fixed integer limit, you can specify a decision variable or expression as the capacity bound:
- Python
- TypeScript
# Variable capacity based on a decision variable
capacity = model.int_var(min=5, max=10, name="capacity")
model.enforce(cumul <= capacity)
// Variable capacity based on a decision variable
let capacity = model.intVar({ min: 5, max: 10, name: "capacity" });
model.enforce(cumul.le(capacity));
This enables modeling scenarios where resource capacity itself is a decision, such as:
- Selecting machine configurations with different capacities
- Optimizing workforce allocation where team size varies
- Capacity planning problems where investment decisions affect limits
Smart Default for Decision Problems
The solutionLimit parameter now defaults to automatic mode: decision problems (without an objective) stop after finding the first solution, while optimization problems continue searching. This eliminates the common pitfall of forgetting to set solutionLimit=1 for satisfaction problems.
New Features
Solver
- Variable resource capacity: Discrete resource constraints now accept decision variables or expressions as capacity bounds
- Preset parameter: One-parameter solver configuration for different problem sizes
- Automatic solution limit: Smart default stops at first solution for decision problems
- Deferred solution values: Performance optimization for large models
- Improved logging: Parameter values now show reasons (preset, auto) and workers are grouped by configuration
- solverArgs parameter: Pass custom command-line arguments to the solver subprocess
TypeScript API Changes (Detail)
The main goal of these changes is to align the TypeScript and Python APIs, making them nearly identical and easier to use across both languages.
All deprecated functions remain functional but are no longer documented. They will be removed in a future release.
Summary of Changes
| Category | Change Pattern |
|---|---|
| Variable properties | Methods → Property accessors |
| Cumulative expressions | cumul prefix removed |
| Step functions | stepFunction prefix removed, clearer names |
| Interval accessors | Of suffix removed |
| Global functions | Moved to class methods |
| Event handlers | on() method → Property setters |
| Result properties | Renamed for clarity |
Variable Classes
Variable properties are now accessed directly as properties instead of through getter/setter methods, making the code more concise and idiomatic.
IntVar
| Deprecated | Replacement |
|---|---|
isOptional() | optional property |
isPresent() | optional property |
isAbsent() | optional property |
getMin() | min property |
getMax() | max property |
makeOptional() | optional = true |
makeAbsent() | optional = null |
makePresent() | optional = false |
setMin(min) | min property |
setMax(max) | max property |
setRange(min, max) | min and max properties |
BoolVar
| Deprecated | Replacement |
|---|---|
isOptional() | optional property |
isPresent() | optional property |
isAbsent() | optional property |
getMin() | min property |
getMax() | max property |
makeOptional() | optional = true |
makeAbsent() | optional = null |
makePresent() | optional = false |
setMin(min) | min property |
setMax(max) | max property |
setRange(min, max) | min and max properties |
IntervalVar
| Deprecated | Replacement |
|---|---|
isOptional() | optional property |
isPresent() | optional property |
isAbsent() | optional property |
makeOptional() | optional = true |
makePresent() | optional = false |
makeAbsent() | optional = null |
getStartMin() | startMin property |
getStartMax() | startMax property |
getEndMin() | endMin property |
getEndMax() | endMax property |
getLengthMin() | lengthMin property |
getLengthMax() | lengthMax property |
setStart(s) | startMin and startMax properties |
setStart(sMin, sMax) | startMin and startMax properties |
setStartMin(sMin) | startMin property |
setStartMax(sMax) | startMax property |
setEnd(e) | endMin and endMax properties |
setEnd(eMin, eMax) | endMin and endMax properties |
setEndMin(eMin) | endMin property |
setEndMax(eMax) | endMax property |
setLength(len) | lengthMin and lengthMax properties |
setLength(lMin, lMax) | lengthMin and lengthMax properties |
setLengthMin(lMin) | lengthMin property |
setLengthMax(lMax) | lengthMax property |
ModelElement
| Deprecated | Replacement |
|---|---|
setName(name) | name property |
getName() | name property |
Model Class
Naming and Constraints
The constraint() method is renamed to enforce() to better convey the intent of adding a constraint to the model.
| Deprecated | Replacement |
|---|---|
setName(name) | name property |
getName() | name property |
constraint(constraint) | enforce(constraint) |
intVar({ range: [a, b] }) | intVar({ min: a, max: b }) |
Interval Accessors
The Of suffix is removed from interval accessor functions for cleaner syntax.
| Deprecated | Replacement |
|---|---|
presenceOf(interval) | presence(interval) |
startOf(interval) | start(interval) |
endOf(interval) | end(interval) |
lengthOf(interval) | length(interval) |
Cumulative Expressions
The cumul prefix is removed; these functions are now overloaded with their integer counterparts (e.g., plus() works for both integers and cumulative expressions).
| Deprecated | Replacement |
|---|---|
cumulSum(args) | sum(args) |
cumulPlus(lhs, rhs) | plus(lhs, rhs) |
cumulMinus(lhs, rhs) | minus(lhs, rhs) |
cumulLe(cumul, max) | le(cumul, max) |
cumulGe(cumul, min) | ge(cumul, min) |
cumulNeg(arg) | neg(arg) |
Step Functions
Step function operations are renamed to use standard mathematical terminology.
| Deprecated | Replacement |
|---|---|
stepFunctionSum(func, interval) | integral(func, interval) |
stepFunctionEval(func, x) | eval(func, x) |
CumulExpr Class
Instance methods mirror the model-level changes, removing the cumul prefix.
| Deprecated | Replacement |
|---|---|
cumulPlus(rhs) | plus(rhs) |
cumulMinus(rhs) | minus(rhs) |
cumulLe(max) | le(max) |
cumulGe(min) | ge(min) |
cumulNeg() | neg() |
IntStepFunction Class
Instance methods mirror the model-level changes, using standard mathematical names.
| Deprecated | Replacement |
|---|---|
stepFunctionSum(interval) | integral(interval) |
stepFunctionEval(x) | eval(x) |
Solver Class
Event Handlers
Event handlers are now assigned as properties instead of using the on() method.
| Deprecated | Replacement |
|---|---|
on('error', listener) | onError property |
on('warning', listener) | onWarning property |
on('log', listener) | onLog property |
on('solution', listener) | onSolution property |
on('objectiveBound', listener) | onObjectiveBound property |
on('lowerBound', listener) | onObjectiveBound property |
on('summary', listener) | onSummary property |
Result Types
SolveSummary
Field names are updated for consistency: lowerBound becomes objectiveBound to reflect that it applies to both minimization and maximization.
| Deprecated | Replacement |
|---|---|
nbWorkers | actualWorkers |
lowerBound | objectiveBound |
SolveResult
The best prefix is removed from field names for brevity, and lowerBound becomes objectiveBound.
| Deprecated | Replacement |
|---|---|
nbWorkers | actualWorkers |
lowerBound | objectiveBound |
bestSolution | solution |
bestSolutionTime | solutionTime |
bestLBTime | boundTime |
bestSolutionValid | solutionValid |
lowerBoundHistory | objectiveBoundHistory |
Global Functions
Standalone functions are moved to class methods for better discoverability and a more object-oriented API.
| Deprecated | Replacement |
|---|---|
calcSolverPath(params) | Solver.findSolver(params) |
solve(model, params, ...) | model.solve(params, ...) |
problem2json(model) | model.toJSON() |
json2problem(json) | Model.fromJSON(json) |
problem2txt(model, ...) | model.toText(...) |
problem2js(model, ...) | model.toJS(...) |
Parameter Parsing
The CLI parameter parsing API has been redesigned to use an options object for better flexibility and consistency.
| Deprecated | Replacement |
|---|---|
parseParameters(params?, args?) | parseParameters(options?) |
parseSomeParameters(params, args?) | parseKnownParameters(options?) |
Parameters.version | Removed (use --optalcpVersion flag) |
Parameters.usage | parseParameters({ usage: "..." }) |
The new functions use an options object:
const params = parseParameters({
args: process.argv.slice(2), // default
defaults: { timeLimit: 60 }, // CLI overrides these
usage: "Usage: myapp [options]",
exitOnError: true // false to throw instead of exit
});
const [params, unknown] = parseKnownParameters({ ... });
The --version flag has been renamed to --optalcpVersion to print solver version information.
Type Aliases (Backward Compatibility)
These type aliases are preserved for backward compatibility but should be migrated to the new names.
| Deprecated | Replacement |
|---|---|
ModelNode | ModelElement |
ObjectiveHistoryItem | ObjectiveEntry |
LowerBoundEvent | ObjectiveBoundEntry |
Solver Parameter Changes
Deprecated (Backward Compatible)
The LB (lower bound) terminology is replaced with Dual to be consistent with optimization literature.
| Deprecated | Replacement |
|---|---|
FDSLB | FDSDual |
Breaking Changes (No Backward Compatibility)
These parameter renames are not backward compatible; old names will cause errors.
| Old Name | New Name |
|---|---|
FDSLBStrategy | FDSDualStrategy |
FDSLBResetRatings | FDSDualResetRatings |
logOutput | printLog |
solverPath | solver |
stepFunctionSumPropagationLevel | integralPropagationLevel |