Repository navigation
Conversation
* Do not track manifest * Bump dependencies and use HiGHS as test solver * Correct type in dictionary * Add field for segment structure and constructors to match old interface * Specialize piecewiselinear for typical 1D and 2D usage * Include segment structure in triangle selection * Update tests to reflect changes, use HiGHS and run all bivariate * Fix triangulation * Avoid explicit use of MOI
…bivariate support
…s, validate inputs
…t D ≥ 3, extend tests
…neric JuMP inputs
…pper/Lower/BestFit, make PWLFunction callable
…s, make the hyperplane representation internal
…overs, documentation from benchmark results
… in its own workflow
…over levels with an empty side
…isaggregatedLogarithmic
…age and covers built by `_triangle_selection_cover`
|
So let's step back and take the opportunity to re-think the API: using JuMP
import HiGHS
import PiecewiseLinearOpt
model = Model(HiGHS.Optimizer)
@variable(model, x)
@variable(model, y)
f = PiecewiseLinearOpt.PiecewiseLinear(sin, 0:0.5:2π)
g = PiecewiseLinearOpt.PiecewiseLinear(
0:0.25:1,
0:0.25:1;
method = SixStencil(ZigZagBinary()),
) do a, b
return (a - 1)^2 + (b - 0.5)^2
end
@objective(model, Min, f(model, x) + g(model, x, y))
optimize!(model)or using JuMP
import HiGHS
import PiecewiseLinearOpt
model = Model(HiGHS.Optimizer)
@variable(model, x[1:2])
f = PiecewiseLinearOpt.PiecewiseLinear(sin, model, 0:0.5:2π)
g = PiecewiseLinearOpt.PiecewiseLinear(
(a, b) -> (a - 1)^2 + (b - 0.5)^2,
model,
0:0.25:1,
0:0.25:1;
method = SixStencil(ZigZagBinary()),
)
@objective(model, Min, f(x[1]) + g(x[1], x[2])) |
|
I kind of like both approaches, maybe the first best, but you would have to think a bit carefully about using a pwl function (with the same variable) twice in the same model, e.g. both in the objective and the constraints. Then each use will have its own set of variables (at least in a naive implementation) which seems kind of inefficient. Binding the function (as now) both to the model and the variable at least avoids these issues. Since variables are attached to a model, a third option is to avoid using JuMP
import HiGHS
import PiecewiseLinearOpt
model = Model(HiGHS.Optimizer)
@variable(model, x)
@variable(model, y)
f = PiecewiseLinearOpt.PiecewiseLinear(sin, 0:0.5:2π)
g = PiecewiseLinearOpt.PiecewiseLinear(
0:0.25:1,
0:0.25:1;
method = SixStencil(ZigZagBinary()),
) do a, b
return (a - 1)^2 + (b - 0.5)^2
end
@objective(model, Min, f(x) + g(x, y))
optimize!(model) |
|
You could do @expression(model, fx, f(x))and then use |
|
Good point. Would you consider such an API to be a complete replacement for the old one? |
|
Yeah I'd say just rip out the old one completely. No need for two ways to do the same thing |
|
What do you think of the API now? |
|
One argument in favor of the original What about doing something like: f = PiecewiseLinear(sin, 0:0.5:2π)
y, formulation = add_formulation(model, f, x)
(f::PiecewiseLinear)(x) = first(add_formulation(owner_model(x), f, x))See MathOptAI for inspiration for the formulation object: https://github.com/lanl-ansi/MathOptAI.jl/blob/77ddd62cc86fd5c565d39b376ce49b4af0341457/src/MathOptAI.jl#L38-L58 |
|
There is already a formulation available (directly inspired by PiecewiseLinearOpt.jl/src/piecewise_linear.jl Lines 272 to 278 in cef5b5a PiecewiseLinear API, but it looks a bit cumbersome.
|
|
I'll setup |
|
Nice nice nice. We have a developer call on Friday. I'll discuss this PR there. |
This PR is a full rewrite of the package based on the work initiated in the PR #40. The rewrite has been done using AI tools (Claude Opus 5.5 and Claude Fable 5.1) in a guided manner. The goal has primarily been to offer the same functionality as the old version, but with a more modern Julia design aligned with other JuMP related packages (e.g.
MathOptAI) and with improved documentation, updated CI and test coverage. A priority was also to make the package easy to extend with new methods.The following is a short summary of the changes as provided by Claude:
Rewrite of PiecewiseLinearOpt.jl (v0.5.0)
This PR rewrites the whole package. It is a breaking release.
What changes
piecewiselinearreturns aPWLFormulation. It accepts scalar, vector and generic JuMP inputs.PWLFunctionis callable, and its structure and method options are concrete type parameters. Univariate, bivariate and D ≥ 3 functions are supported, and you can pass triangulations or value matrices.Graph(),Epigraph()andHypograph()set the direction. NewUnivariatePWLRelaxationandConvexPiecesadd binaries only for the convex pieces in the relaxed direction.GreedyTriangleSelectionadded. It is the upper bound and fallback forOptimalTriangleSelection, which caches covers and has time limits.MultipleChoiceadded, with exact coefficients.PWLMethod,SOS2Method,TriangleSelectionMethod,Scalar, segment accessors andcell_diagonalsare now public and documented..h5instance files and the exhaustive tests are removed.Migration
Code written for v0.4 needs updating. See the docs for the new
piecewiselinear/PWLFunctionAPI and the method names.🤖 Generated with Claude Code